Dlaczego używamy interfejsu? Czy dotyczy tylko normalizacji? [Zamknięte]

79

Dlaczego używamy interfejsu?

Czy dotyczy tylko normalizacji?

Azhar
źródło
1
w przeciwieństwie do ...? interfejsy mają wiele zastosowań ...
Jason,
6
Naprawdę chciałbym, aby ludzie nie umieszczali tagów takich jak C # w postach, które nie są specyficzne dla języka C #. To naprawdę świetne pytanie i mogłem je przeoczyć, ponieważ c # to zignorowany tag.
Tyler Carter

Odpowiedzi:

171

Cele interfejsów

  • tworzyć luźno powiązane oprogramowanie
  • wsparcie projektowania na podstawie umowy (wykonawca musi zapewnić cały interfejs)
  • pozwalają na podłączane oprogramowanie
  • pozwalają na łatwą interakcję różnych obiektów
  • ukryj szczegóły implementacji klas przed sobą
  • ułatwiać ponowne wykorzystanie oprogramowania

Analogia 1 : Podobnie jak amerykański prom kosmiczny, rosyjski statek kosmiczny Sojuz i chiński Shenzhou 5 mogą zadokować na Międzynarodowej Stacji Kosmicznej, ponieważ mają ten sam interfejs dokowania. (To tylko przykład - nie wiem, czy to prawda w prawdziwym życiu, ale zawieśmy nasze niedowierzanie dla przykładu)

Analogia 2 : Tak jak możesz podłączyć różne monitory komputerowe do komputera domowego. Można do niego podłączyć ścienny telewizor, stary kineskop (gruby), 20-calowy płaski ekran lub brajlowską maszynę dla niewidomych, aby „widzieć” dotykiem. Jest kompatybilność między tymi różnymi / różnymi urządzeniami i komputer, ponieważ wszyscy zgadzają się ze standardami interfejsów.

Szczegóły interfejsów C # - z interfejsami C # / OOP robisz to samo, ale w niewidocznym / wirtualnym świecie.

Masz rację co do standaryzacji , ale także elastyczności , skalowalności , rozszerzalności , łatwości konserwacji , możliwości ponownego wykorzystania , testowalności i mocy .

(Im częściej używasz interfejsów programowych, tym lepiej zrozumiesz te „modne słowa”. Zawsze rozważaj interfejsy w prawdziwym świecie, ponieważ zrobiły to dla nas równie dobrze).

John K.
źródło
18
Pominęliście moje ulubione zastosowanie interfejsów: testowalność. Jeśli mam dwie klasy, A i B i A.foo wywołuje B.bar, to tak długo, jak B implementuje interfejs i można go „wstrzyknąć” do A, mogę użyć klasy pozorowanej, fałszywej lub pośredniczącej zamiast prawdziwe B. Jest to szczególnie przydatne, gdy A.foo zmienia swoje zachowanie w oparciu o wartość zwracaną z B.bar. (Powiedzmy, że B.bar zwraca bool. A.foo może mieć instrukcję if (B.bar) z klauzulą ​​else.) Użycie interfejsu w B pozwala mi stworzyć mockB, fakeB i / lub stubB, które pozwalają mi przetestować dzieje się, gdy B.bar zwraca prawdę lub fałsz.
aridlehoover
Dodano test @Alan R. Dzięki.
John K
1
Zaakceptowaną odpowiedzią jest NAJLEPSZA rzecz i odświeżające jest to, że koncepcja nie została odrzucona, ponieważ większość materiałów zawierających wytyczne dotyczące projektowania ram nie wyjaśnia jej ani nie rozumie. Dodam tylko, że jeśli poważnie używasz generyków, nie wiem, jak ci się bez nich obejść.
rama-jka toti
6
+1 dlastandardization, but also flexibility, scalability, extensibility, maintainability, reusability, testability and power.
Ravi
29

Interfejs jest używany do opisania tego, co może zrobić zaimplementowana rzecz. Masz więc możliwość traktowania kilku obiektów, które implementują ten sam interfejs, jako typ tego interfejsu.

Na przykład:

public interface IMyInterface{
    public void DoFirst();
    public int DoSecond();
}


public class A : IMyInterface{
   //class has to implement DoFirst and DoSecond
   public void DoFirst(){
     Console.WriteLine("Blubb1");  
   }

   public int DoSecond(){
     Console.WriteLine("Blubb2");
     return 2;  
   }
}

public class B : IMyInterface{
   //class has to implement DoFirst and DoSecond
   public void DoFirst(){
     Console.WriteLine("Blibb1");  
   }

   public int DoSecond(){
     Console.WriteLine("Blibb2");  
     return 4;
   }
}

Klasy implementują interfejs na kilka sposobów. Ale możesz ich używać jako IMyInterface. Na przykład:

public static void DoMethodsInInterface(IMyInterface inter){
    inter.DoFirst();
    inter.DoSecond();
}


public static void main(){

   DoMethodsInInterface(new A());
   DoMethodsInInterface(new B());
   //Or use it in a List
   List<IMyInterface> interlist = new List<IMyInterface>();
   interlist.Add(new A());
   interlist.Add(new B());
   foreach(IMyInterface inter in interlist){
      inter.DoFirst();
   }

}

Mam nadzieję, że to wyjaśnia nieco, dlaczego interfejsy są przydatne.

jaskółka oknówka
źródło
2
To pytanie było powiązane z pytaniem, które pyta, dlaczego należy używać interfejsów zamiast po prostu mieć członków, którzy wykonują odpowiednie funkcje itp., A Twoja odpowiedź jest najbliższa odpowiedzi na to pytanie. Gdyby dwie niepowiązane klasy miały metodę Woozle, dowolny kod, który chciałby zaakceptować odwołanie do którejkolwiek z klas i Woozlemusiałby wiedzieć, z którą klasą ma do czynienia, i byłby w stanie tylko te Woozleklasy, o których wiedział. Z drugiej strony, jeśli obie klasy implementują IWoozler, to kod, który jest podany, IWoozlermoże Woozleto zrobić bez konieczności znajomości jego dokładnego typu.
supercat
Ta odpowiedź jest lepsza niż wszystkie, które widziałem. Chodzi o to, co może zrobić przedmiot. Interfejsy określają zestaw działań związanych z obiektem bez narzucania tego, co dzieje się w ramach tych akcji, które oczywiście byłyby specyficzne dla obiektu.
m12lrpv
5

Służy do łączenia się :), abyś mógł połączyć się między rzeczami, jest to przydatne, gdy masz

  • wiele implementacji tego samego materiału
  • kiedy stosujesz interfejs do wielu różnych klas, ponieważ potrzebujesz jakiejś konwencji, że te klasy będą w stanie coś zrobić lub mieć jakąś funkcjonalność
Omu
źródło
3

Oto widok wysokiego poziomu ...

Interfejsy odgrywają dużą rolę w koncepcji ukrywania informacji .

Zasadniczo pomagają one ukryć szczegóły implementacji Twojej klasy, dzięki czemu klasa wywołująca nie jest zależna od tej implementacji. W związku z tym za pomocą interfejsów można modyfikować implementację bez zmiany klasy wywołującej. To wszystko z kolei ogranicza złożoność kodu i ułatwia jego utrzymanie w dłuższej perspektywie.

Kiedy po raz pierwszy zacząłem rozumieć interfejsy, wyjaśniono mi je jako „kontrakt, który zawiera opis Twojej klasy”. Nie jestem pewien, czy to ci pomoże, ale jeśli pomyślisz o interfejsie do samochodu, możesz powiedzieć, że jeździ , psuje się i skręca . Tak długo, jak prowadzi mnie z punktu A do punktu B, tak naprawdę nie muszę wiedzieć, jak te funkcje są implementowane.

matt_dev
źródło
2

Głównym powodem, dla którego interfejsy są używane w językach takich jak C # / Java, jest to, że języki te nie obsługują dziedziczenia wielokrotnego (klasowego) (zobacz Jaki jest dokładny problem z dziedziczeniem wielokrotnym? ).

Jednak dozwolona jest wielokrotna implementacja (interfejs), co pozwala na używanie klas na różne sposoby.

Catalin DICU
źródło
1
Interfejsy w językach zarządzanych NIE zastępują dziedziczenia wielokrotnego. Nawet w językach, które obsługują wielokrotne dziedziczenie, koncepcja interfejsu bez implementacji jest odpowiednia i użyteczna. (Zobacz zastrzyk zależności.)
aridlehoover
1
-1 niezbyt dobrze przemyślane, czy naprawdę nie rozumiesz C # lub Java?
John Saunders
Chcę tylko powiedzieć, że w C ++ zamiast interfejsów można używać czystych klas abstrakcyjnych. Większość rzeczy, które możesz zrobić w Javie / C # za pomocą interfejsów, które możesz zrobić w C ++ z czystymi klasami abstrakcyjnymi. W C ++, jeśli chcesz, aby klasa miała wiele zachowań, odziedziczyłeś wiele czystych klas abstrakcyjnych. Ale nie możesz tego zrobić w Javie / C #. Nie mówię, że interfejsy nie są "użyteczne", mówię więcej: języki takie jak Java i C # nie byłyby tak naprawdę językami programowania obiektowego bez dziedziczenia wielu interfejsów. (nie zezwalają na dziedziczenie wielu klas ani mieszanie)
Catalin DICU
1
+1 To jest zasadniczo to, co zostało odkryte na własnej skórze dzięki doświadczeniom C # i Javy. Jeśli spróbujesz uprościć, unikając wielokrotnego dziedziczenia, po prostu tworzysz złożoność gdzie indziej. Z powodu braku ujednolicającego podstawowego podejścia, uzyskujesz gorszą złożoność. Patrz adnotacja Krzysztofa Cwaliny w języku programowania C # 3. wydanie , 1.9 Interfaces, która dokładnie to mówi. Na chwilę obecną nadal istnieją nierozwiązane problemy w językach C # i Java, które miałyby proste rozwiązania, gdyby było dozwolone wielokrotne dziedziczenie klas.
Daniel Earwicker,
Dziedziczenie -1 i interfejsy są naprawdę bardzo różne.
kenny
2

Interfejsy są nieco niewygodne. Wspierają projektowanie na podstawie umowy tylko wierząc, że ta sama nazwa i zaimplementowany interfejs oznaczają takie samo zachowanie. Działa to tylko dzięki dokumentacji API, musi zostać sprawdzone przez człowieka. To sprawia, że ​​interfejsy są zbyt słabe. Jednym ze sposobów obejścia tego może być formalna specyfikacja. Z drugiej strony interfejsy są zbyt mocne, zbyt rygorystyczne. Nie można rozwijać interfejsów, które często przeszkadzają w ponownym użyciu. Rozwiązują to protokoły - mechanizm w językach dynamicznych, które wysyłają wiadomości (metody wywołania) i gdy ta wiadomość nie jest obsługiwana przez odbiorcę, wywoływane jest standardowe callback. Posiadanie konkretnych protokołów z ograniczeniami byłoby o wiele lepsze.

Gabriel Ščerbák
źródło
1

Myśl zdalnie ...

W grę wchodzi klient i serwer. Powiedzmy, że są fizycznie oddzielone przez internet. Klient wywołuje metodę, której rzeczywiste wykonanie odbywa się na serwerze. Z punktu widzenia klienta klient nie wie nic o obiekcie na serwerze, który wykonuje wykonanie. Jednak wie, jaką metodę wywołać. Ponieważ budując program klienta, jesteśmy narażeni tylko na interfejs (lub kontrakt). Nie jesteśmy narażeni na cały obiekt, który faktycznie żyje na serwerze. Spróbuj zrobić kilka aplikacji demonstracyjnych w zdalnej usłudze .net, a zajmiesz się resztą. Miłego programowania.

deostroll
źródło
0

Dlaczego używamy interfejsów?

Niektóre języki wdrożyć polimorficzne połączeń Metoda z zastosowaniem vtables i wyrzucić większość informacji typu utrudniając nie zdefiniowanie interfejsów.

Więc czasami po prostu używamy interfejsów, ponieważ wymaga tego projekt języka.

Alex Jasmin
źródło
0

Rozpoczynając od interfejsu, można zaimplementować proxy , pozwalając w ten sposób na leniwe ładowanie lub przeprowadzanie pewnych weryfikacji podczas wywoływania metod konkretnej implementacji.

lmsasu
źródło
0

Interfejs oddziela typ danych od logiki implementacji.

Anand
źródło
0

Interfejs dostarcza prototypowego modalu, który zawiera tylko deklarację funkcjonalności określonego zachowania.

a jeśli chcesz zaimplementować to zachowanie w klasie, musisz zaimplementować ten interfejs w klasie, a następnie klasa ma taką funkcjonalność zachowania lub może mieć wiele zachowań.

ponieważ klasa może implementować wiele interfejsów.

Manoj Gupta
źródło