Co to znaczy "programować do interfejsu"?

Widziałem to już kilka razy i nie wiem, co to znaczy. Kiedy i dlaczego to zrobiłeś?

Wiem, co robią interfejsy, ale fakt, że nie jestem w tym jasny, sprawia, że myślę, że brakuje mi ich prawidłowego użycia.

Czy tak jest, gdybyś miał to zrobić:

IInterface classRef = new ObjectWhatever()
Możesz użyć dowolnej klasy, która implementuje IInterface? Kiedy miałbyś to zrobić? Jedyne, o czym mogę myśleć, to jeśli masz metodę i nie jesteś pewien, jaki przedmiot zostanie przekazany expect for it implementing IInterface. Nie wiem, jak często musiałbyś to robić... (Również, jak można napisać metodę, która bierze w obiekt, który implementuje interfejs? Czy to możliwe?) Przepraszam, jeśli całkowicie przeoczyłem sedno sprawy.
Author: Sameer, 2008-12-21

30 answers

Jest tu kilka wspaniałych odpowiedzi na te pytania, które wnikają w różnego rodzaju szczegóły dotyczące interfejsów i luźnego sprzężenia kodu, inwersji sterowania i tak dalej. Istnieje kilka dość nagłych dyskusji, więc chciałbym skorzystać z okazji, aby podzielić rzeczy w dół trochę dla zrozumienia, dlaczego interfejs jest przydatny.

Kiedy po raz pierwszy zacząłem narażać się na Interfejsy, też byłem zdezorientowany co do ich znaczenia. Nie rozumiem, dlaczego ich potrzebujesz. Jeśli używamy język taki jak Java czy C#, mamy już dziedziczenie i postrzegałem interfejsy jako słabszą formę dziedziczenia i pomyślałem: "po co się przejmować?"W pewnym sensie miałem rację, można myśleć o interfejsach jako o słabej formie dziedziczenia, ale poza tym w końcu zrozumiałem ich użycie jako konstrukcji języka, myśląc o nich jako o sposobie klasyfikowania wspólnych cech lub zachowań, które były eksponowane przez potencjalnie wiele niepowiązanych klas obiektów.

Na przykład -- say you posiadaj grę SIM i posiadaj następujące klasy:

 class HouseFly inherits Insect {
   void FlyAroundYourHead(){}
   void LandOnThings(){}
 }

 class Telemarketer inherits Person {
   void CallDuringDinner(){}
   void ContinueTalkingWhenYouSayNo(){}
 }
Najwyraźniej te dwa obiekty nie mają ze sobą nic wspólnego w kwestii bezpośredniego dziedziczenia. Ale można powiedzieć, że obie są irytujące.

Powiedzmy, że nasza gra musi mieć jakąś przypadkową rzecz , która denerwuje gracza, gdy je obiad. To może być HouseFly lub Telemarketer lub jedno i drugie -- ale jak można pozwolić na jedno i drugie za pomocą jednej funkcji? I jak prosić każdy inny rodzaj obiektu, aby " robił swoje irytująca rzecz" w ten sam sposób?

Kluczem do zrozumienia jest to, że zarówno Telemarketer jak i HouseFly mają wspólne, luźno interpretowane zachowanie, mimo że nie są do siebie podobne pod względem ich modelowania. Stwórzmy więc interfejs, który może zaimplementować oba:

 interface IPest {
    void BeAnnoying();
 }

 class HouseFly inherits Insect implements IPest {
   void FlyAroundYourHead(){}
   void LandOnThings(){}

   void BeAnnoying() {
     FlyAroundYourHead();
     LandOnThings();
   }
 }

 class Telemarketer inherits Person implements IPest {
   void CallDuringDinner(){}
   void ContinueTalkingWhenYouSayNo(){}

   void BeAnnoying() {
      CallDuringDinner();
      ContinueTalkingWhenYouSayNo();
   }
 }

Mamy teraz dwie klasy, które mogą być irytujące na swój sposób. I nie muszą wywodzić się z tej samej klasy bazowej i mieć wspólnych, nieodłącznych cech-po prostu muszą spełnić kontrakt IPest -- ten kontrakt jest prosty. Musisz tylko BeAnnoying. W związku z tym możemy modelować:

 class DiningRoom {

   DiningRoom(Person[] diningPeople, IPest[] pests) { ... }

   void ServeDinner() {
     when diningPeople are eating,

       foreach pest in pests
         pest.BeAnnoying();
   }
 }

Tutaj mamy jadalnię, która przyjmuje wiele jadalni i wiele szkodników -- zwróć uwagę na korzystanie z interfejsu. Oznacza to, że w naszym małym świecie, członkiem tablicy pests może być obiekt Telemarketer lub obiekt HouseFly.

Metoda ServeDinner nazywa się, kiedy serwowana jest kolacja, a nasi ludzie w jadalni mają jeść. W naszej małej grze, wtedy nasze szkodniki wykonują swoją pracę - każdy szkodnik jest poinstruowany, aby być irytującym za pomocą interfejsu IPest. W ten sposób możemy łatwo mieć zarówno Telemarketers, jak i HouseFlys być irytującymi na każdy z ich sposobów-zależy nam tylko na tym, że w obiekcie DiningRoom mamy coś, co jest szkodnikiem, tak naprawdę nie zależy nam, co to jest i nie mogą mieć nic wspólnego z innymi.

Ten bardzo wymyślny przykład pseudo-kodu (który przeciągał się o wiele dłużej, niż się spodziewałem) ma po prostu zilustrować rodzaj coś, co w końcu włączyło światło dla mnie, jeśli chodzi o to, kiedy możemy użyć interfejsu. Z góry przepraszam za głupotę przykładu, ale mam nadzieję, że pomoże to w zrozumieniu. I, aby mieć pewność, inne opublikowane odpowiedzi, które tu otrzymałeś, naprawdę obejmują gamę wykorzystania interfejsów dzisiaj w wzorcach projektowych i metodologiach rozwoju.

 1433
Author: Peter Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-30 01:45:15

Konkretnym przykładem, który dałem uczniom, jest to, że powinni napisać

List myList = new ArrayList(); // programming to the List interface

Zamiast

ArrayList myList = new ArrayList(); // this is bad

Wyglądają dokładnie tak samo w krótkim programie, ale jeśli użyjesz myList 100 razy w swoim programie, możesz zacząć dostrzegać różnicę. Pierwsza deklaracja zapewnia, że wywołujesz tylko metody myList, które są zdefiniowane przez interfejs List (więc nie ma konkretnych metod ArrayList). Jeśli zaprogramowałeś interfejs w ten sposób, później możesz zdecydować, że really need

List myList = new TreeList();

I musisz tylko zmienić swój kod w tym jednym miejscu. Wiesz już, że reszta twojego kodu nie robi nic, co zostanie złamane przez zmianę implementacji ponieważ zaprogramowałeś do interfejsu .

Korzyści są jeszcze bardziej oczywiste (myślę), gdy mówimy o parametrach metody i wartościach zwrotnych. Weźmy na przykład:

public ArrayList doSomething(HashMap map);

Ta deklaracja metody łączy cię z dwoma konkretnymi implementacjami (ArrayList i HashMap). Jak tylko ta metoda zostanie wywołana z innego kodu, wszelkie zmiany w tych typach prawdopodobnie oznaczają, że będziesz musiał również zmienić kod wywołujący. Lepiej byłoby zaprogramować do interfejsów.

public List doSomething(Map map);

Teraz nie ma znaczenia, jakiego rodzaju List zwracasz, ani jaki rodzaj {[12] } jest przekazywany jako parametr. Zmiany wprowadzone wewnątrz metody doSomething nie zmuszą cię do zmiany kodu wywołującego.

 235
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-12 14:46:40

Programowanie interfejsu mówi: "potrzebuję tej funkcjonalności i nie obchodzi mnie, skąd pochodzi."

Rozważmy (w Javie), interfejs List kontra konkretne klasy ArrayList i LinkedList. Jeśli interesuje mnie tylko to, że mam strukturę danych zawierającą wiele elementów danych, do których powinienem uzyskać dostęp poprzez iterację, wybrałbym List (i to w 99% przypadków). Jeśli Wiem, że muszę wstawiać/usuwać z każdego końca listy, mogę wybrać LinkedList concrete implementacja (lub bardziej prawdopodobne, użycie interfejsu Queue ). Jeśli Wiem, że potrzebuję losowego dostępu przez indeks, wybrałbym klasę ArrayList concrete.

 64
Author: kdgregory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-21 06:48:17

Używanie interfejsów jest kluczowym czynnikiem ułatwiającym testowanie kodu, oprócz usuwania zbędnych powiązań między klasami. Tworząc interfejs, który definiuje operacje na klasie, pozwalasz klasom, które chcą korzystać z tej funkcjonalności, na korzystanie z niej bez polegania bezpośrednio na klasie implementującej. Jeśli później zdecydujesz się zmienić i użyć innej implementacji, wystarczy zmienić tylko część kodu, w której implementacja jest tworzona. Reszta kodu nie musi się zmieniać, ponieważ zależy to od interfejsu, a nie klasy implementującej.

Jest to bardzo przydatne w tworzeniu testów jednostkowych. W testowanej klasie zależy od interfejsu i wstrzykuje instancję interfejsu do klasy (lub fabryki, która pozwala mu budować instancje interfejsu w razie potrzeby) za pomocą konstruktora lub właściwości settor. Klasa używa dostarczonego (lub utworzonego) interfejsu w swoich metodach. Kiedy idziesz pisać testy, może sfałszować lub sfałszować interfejs i zapewnić interfejs, który reaguje z danymi skonfigurowanymi w teście jednostkowym. Możesz to zrobić, ponieważ twoja klasa w trakcie testu zajmuje się tylko interfejsem, a nie konkretną implementacją. Zrobi to każda klasa implementująca interfejs, w tym twoja klasa mock lub fake.

EDIT: Poniżej znajduje się link do artykułu, w którym Erich Gamma omawia swój cytat, " Program do interfejsu, a nie wdrożenie."

Http://www.artima.com/lejava/articles/designprinciples.html

 35
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 01:58:53

Należy przyjrzeć się inwersji sterowania:

W takim scenariuszu nie napisałbyś tego:

IInterface classRef = new ObjectWhatever();

Napisałbyś coś takiego:

IInterface classRef = container.Resolve<IInterface>();

To przejdzie do konfiguracji opartej na regułach w obiekcie container i zbuduje dla Ciebie rzeczywisty obiekt, który może być obiektem niezależnie od tego. Ważne rzecz w tym, że możesz zastąpić tę regułę czymś, co w ogóle używało innego typu obiektu, a Twój kod nadal będzie działał.

Jeśli zostawimy IoC poza tabelą, możesz napisać kod, który wie, że może rozmawiać z obiektem , który robi coś konkretnego , ale nie jakiego typu obiekt lub jak to robi.

Przydałoby się to przy przekazywaniu parametrów.

Co do twojego pytania " również, jak możesz napisać metodę, która przyjmuje obiekt, który implementuje interfejs? Czy to możliwe?", w C# można po prostu użyć typu interfejsu dla parametru type, jak to:

public void DoSomethingToAnObject(IInterface whatever) { ... }

To podłącza się bezpośrednio do " rozmowy z obiektem, który robi coś konkretnego."Metoda zdefiniowana powyżej wie, czego można się spodziewać po obiekcie, że implementuje wszystko w interfejsie, ale nie obchodzi ją, jaki to jest typ obiektu, tylko to, że przylega do umowy, czyli czym jest interfejs.

Na przykład, prawdopodobnie znasz z kalkulatorów i prawdopodobnie używane sporo w swoich dniach, ale większość czasu są one różne. Ty, z drugiej strony, wiesz, jak powinien działać standardowy kalkulator, więc jesteś w stanie korzystać z nich wszystkich, nawet jeśli nie możesz użyć konkretnych funkcji, które każdy Kalkulator ma, a żaden z innych nie ma.

To jest piękno interfejsów. Możesz napisać kawałek kodu, który wie, że otrzyma obiekty przekazane do niego, od których może oczekiwać określonego zachowania. Nie obchodzi mnie to. hoot jaki to obiekt, tylko że obsługuje zachowanie potrzebne. Pozwól, że podam Ci konkretny przykład.

Mamy niestandardowy system tłumaczenia Dla windows forms. Ten system zapętla kontrolki na formularzu i przetłumaczyć tekst w każdym. System wie, jak obsługiwać podstawowe kontrolki, takie jak-type-of-control-that-has-a-Text-property, i podobne podstawowe rzeczy, ale w przypadku wszystkiego, co podstawowe, nie jest to wystarczające.

Teraz, ponieważ kontrolki dziedziczą z predefiniowanych klas, które nie mamy kontroli nad, możemy zrobić jedną z trzech rzeczy:

  1. Zbuduj wsparcie dla naszego systemu tłumaczeń, aby wykryć, z jakim typem sterowania pracuje, i przetłumaczyć poprawne bity (koszmar konserwacyjny)
  2. budowanie wsparcia w klasach bazowych (niemożliwe, ponieważ wszystkie kontrolki dziedziczą z różnych predefiniowanych klas)
  3. Dodaj obsługę interfejsu
Więc zrobiliśmy nr. 3. Wszystkie nasze kontrolki implementują ILocalizable, czyli interfejs, który daje nam jedną metodę, możliwość przetłumaczenia" siebie " na kontener tekstu/reguł tłumaczenia. Jako taki, formularz nie musi wiedzieć, jaki rodzaj kontroli znalazł, tylko że implementuje określony interfejs i wie, że istnieje metoda, w której może wywołać lokalizację kontroli.
 34
Author: Lasse Vågsæther Karlsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 02:03:05

Programowanie do interfejsu nie ma absolutnie nic wspólnego z abstrakcyjnymi interfejsami, jak widzimy w Javie czy. NET. nie jest to nawet pojęcie OOP.

To naprawdę oznacza, że nie mieszaj się z wewnętrznymi obiektami lub strukturą danych. Użyj abstrakcyjnego interfejsu programu lub API, aby wchodzić w interakcje z danymi. W języku Java lub C# oznacza to używanie publicznych właściwości i metod zamiast surowego dostępu do pól. Dla C oznacza to Używanie funkcji zamiast surowych wskaźników.

EDIT: I w przypadku baz danych oznacza to używanie widoków i procedur składowanych zamiast bezpośredniego dostępu do tabeli.

 28
Author: Jonathan Allen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-19 20:06:39

Kod do interfejsu ani implementacja nie ma nic wspólnego z Javą, ani z jej konstrukcją interfejsu.

Ta koncepcja została wyeksponowana w Patterns / gangu czterech książek, ale prawdopodobnie była około dużo wcześniej. [5]}koncepcja z pewnością istniała na długo przed pojawieniem się Javy.

Java interface construct został stworzony, aby pomóc w tej idei (między innymi), a ludzie stali się zbyt skupieni na konstrukcji jako centrum znaczenie, a nie pierwotny zamiar. Jest to jednak powód, dla którego mamy publiczne i prywatne metody i atrybuty w Javie, C++, C# itp.

Oznacza po prostu interakcję z publicznym interfejsem obiektu lub systemu. Nie martw się, ani nawet nie przewiduj, jak robi to, co robi wewnętrznie. Nie martw się o to, jak to jest realizowane. W kodzie obiektowym, dlatego mamy metody / atrybuty publiczne i prywatne. Zamierzamy używać metod publicznych, ponieważ metody prywatne istnieją tylko dla używaj wewnętrznie, w ramach klasy. Tworzą one implementację klasy i mogą być zmieniane zgodnie z wymaganiami bez zmiany publicznego interfejsu. Załóżmy, że jeśli chodzi o funkcjonalność, metoda na klasie wykona tę samą operację z tym samym oczekiwanym wynikiem za każdym razem, gdy wywołasz ją z tymi samymi parametrami. Pozwala to autorowi zmienić sposób działania klasy, jej implementację, bez przerywania interakcji ludzi z nią.

i można programować do interfejsu, a nie do implementacja bez użycia konstrukcji interfejsu. można programować do interfejsu, a nie do implementacji w C++, która nie ma konstrukcji interfejsu. Można zintegrować dwa potężne systemy korporacyjne znacznie bardziej solidnie, o ile współdziałają one poprzez publiczne interfejsy (umowy), a nie wywołują metody na obiektach wewnętrznych systemów. Interfejsy powinny zawsze reagować w ten sam sposób, biorąc pod uwagę te same parametry wejściowe; jeśli zostaną zaimplementowane do interfejsu a nie realizacja. Koncepcja sprawdza się w wielu miejscach.

Wstrząsnąć myślą, że interfejsy Javy mają cokolwiek wspólnego z pojęciem "Program do Interfejsu, nie implementacji". Mogą pomóc w zastosowaniu koncepcji, ale nie są koncepcją.

 21
Author: Bill Rosmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-21 21:21:22

Wygląda na to, że rozumiesz, jak działają interfejsy, ale nie jesteś pewien, kiedy z nich korzystać i jakie korzyści oferują. Oto kilka przykładów, kiedy interfejs miałby sens:

// if I want to add search capabilities to my application and support multiple search
// engines such as google, yahoo, live, etc.

interface ISearchProvider
{
    string Search(string keywords);
}

Wtedy mógłbym stworzyć GoogleSearchProvider, YahooSearchProvider, LiveSearchProvider itp.

// if I want to support multiple downloads using different protocols
// HTTP, HTTPS, FTP, FTPS, etc.
interface IUrlDownload
{
    void Download(string url)
}

// how about an image loader for different kinds of images JPG, GIF, PNG, etc.
interface IImageLoader
{
    Bitmap LoadImage(string filename)
}

Następnie utwórz JpegImageLoader, GifImageLoader, PngImageLoader, itd.

Większość dodatków i systemów wtyczek działa poza interfejsami.

Innym popularnym zastosowaniem jest repozytorium wzór. Powiedzmy, że chcę załadować listę kodów pocztowych z różnych źródeł

interface IZipCodeRepository
{
    IList<ZipCode> GetZipCodes(string state);
}

Następnie mogę utworzyć XMLZipCodeRepository, Sqlzipcoderepository, CSVZipCodeRepository, itp. Dla Moich aplikacji internetowych często tworzy repozytoria XML na początku, więc mogę dostać coś i działa przed bazy danych Sql jest gotowy. Gdy baza danych jest gotowa, piszę SQLRepository, aby zastąpić wersję XML. Reszta mojego kodu pozostaje bez zmian, ponieważ działa soley off z interfejsy.

Metody mogą przyjmować interfejsy takie jak:

PrintZipCodes(IZipCodeRepository zipCodeRepository, string state)
{
    foreach (ZipCode zipCode in zipCodeRepository.GetZipCodes(state))
    {
        Console.WriteLine(zipCode.ToString());
    }
}
 12
Author: Todd Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 04:50:48

To sprawia, że Twój kod jest dużo bardziej rozszerzalny i łatwiejszy do utrzymania, gdy masz zestawy podobnych klas. Jestem młodszym programistą, więc nie jestem ekspertem, ale właśnie skończyłem projekt, który wymagał czegoś podobnego.

Pracuję na oprogramowaniu po stronie klienta, które rozmawia z serwerem z urządzeniem medycznym. Opracowujemy nową wersję tego urządzenia, która ma kilka nowych komponentów, które klient musi czasami skonfigurować. Są dwa rodzaje nowych komponentów i są różne, ale są one również bardzo podobne. W zasadzie, musiałem utworzyć dwa formularze config, dwie klasy list, dwa wszystkiego.

Zdecydowałem, że najlepiej będzie utworzyć abstrakcyjną klasę bazową dla każdego typu sterowania, która będzie zawierała prawie wszystkie rzeczywiste logiki, a następnie typy pochodne, aby zająć się różnicami między tymi dwoma komponentami. Jednak klasy bazowe nie byłyby w stanie wykonywać operacji na tych komponentach, gdybym musiał cały czas martwić się typami (cóż, mogą have, ale w każdej metodzie byłaby Instrukcja "if" lub switch).

Zdefiniowałem prosty interfejs dla tych komponentów i wszystkie klasy bazowe rozmawiają z tym interfejsem. Teraz, gdy coś zmieniam, to prawie "działa" wszędzie i nie mam duplikacji kodu.

 10
Author: Ed S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 01:07:05

Jeśli programujesz w Javie, JDBC jest dobrym przykładem. JDBC definiuje zestaw interfejsów, ale nie mówi nic o implementacji. Twoje aplikacje mogą być pisane na podstawie tego zestawu interfejsów. Teoretycznie można wybrać jakiś sterownik JDBC i aplikacja będzie po prostu działać. Jeśli odkryjesz, że istnieje szybszy, "lepszy" lub tańszy sterownik JDBC lub z jakiegokolwiek powodu, możesz ponownie teoretycznie ponownie skonfigurować plik właściwości i bez konieczności wprowadzania jakichkolwiek zmian w aplikacji, Twoim aplikacja nadal będzie działać.

 8
Author: Kevin Le - Khnle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 01:20:57

Programowanie do interfejsów jest niesamowite, sprzyja luźnemu sprzężeniu. Jak wspomniał @lassevk, Inwersja sterowania jest świetnym zastosowaniem tego.

Ponadto przyjrzyj się solidnym zleceniodawcom . oto seria wideo

Przechodzi przez mocno zakodowany (silnie sprzężony przykład), a następnie patrzy na Interfejsy, w końcu przechodzi do Narzędzia IOC / DI (NInject)

 8
Author: dbones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-30 13:03:26

Oprócz już wybranej odpowiedzi (i różnych postów informacyjnych tutaj), gorąco polecam chwycić kopię Head First Design Patterns . Jest to bardzo łatwe do odczytania i odpowie bezpośrednio na twoje pytanie, wyjaśni, dlaczego jest to ważne i pokaże Ci wiele wzorców programistycznych, których możesz użyć, aby skorzystać z tej zasady (i innych).

 6
Author: whaley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-08 21:32:05

Wiele wyjaśnień, ale żeby było jeszcze prościej. Weźmy na przykład List. Można zaimplementować listę za pomocą as:

  1. tablica wewnętrzna
  2. a linked list
  3. inne wdrożenie

Budując interfejs, powiedzmy List. Piszesz tylko co do definicji listy lub co List oznacza w rzeczywistości.

Można użyć dowolnego typu implementacji wewnętrznie powiedzieć array implementacji. Ale załóżmy, że chcesz zmienić implementacja z jakiegoś powodu mówi błąd lub wydajność. Następnie wystarczy zmienić deklarację List<String> ls = new ArrayList<String>() na List<String> ls = new LinkedList<String>().

No gdzie jeszcze w kodzie, trzeba będzie coś zmienić; bo wszystko inne zostało zbudowane na definicji List.

 6
Author: Jatin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-09 06:46:33

Jestem spóźniony na to pytanie, ale chcę tutaj wspomnieć, że wiersz "Program do interfejsu, a nie implementacji" miał dobrą dyskusję w książce wzorców projektowych Gof (Gang of Four).

Stwierdził, na str. 18:

Program do interfejsu, a nie implementacji

Nie deklaruj zmiennych jako instancji konkretnych klas. Zamiast tego Zatwierdź tylko interfejs zdefiniowany przez klasę abstrakcyjną. Przekonasz się, że jest to wspólny temat wzorców projektowych w tej książce.

A powyżej zaczęło się od:

Manipulowanie obiektami ma dwie zalety wyłącznie pod względem interfejsu zdefiniowanego przez klasy abstrakcyjne:

  1. klienci pozostają nieświadomi specyficznych typów obiektów, których używają, o ile obiekty przylegają do interfejsu, którego oczekują klienci.
  2. klienci pozostają nieświadomi klas implementujących te obiekty. Klienci wiedzą tylko o klasy abstrakcyjne definiujące interfejs.

Innymi słowy, nie pisz jej tak, aby miała metodę quack() dla kaczek, a następnie metodę bark() dla psów, ponieważ są one zbyt specyficzne dla konkretnej implementacji klasy (lub podklasy). Zamiast tego napisz metodę używając nazw, które są na tyle ogólne, że mogą być używane w klasie bazowej, takich jak giveSound() lub move(), aby mogły być używane dla kaczek, psów, a nawet samochodów, a Klient twojej klasy może po prostu powiedz .giveSound() zamiast zastanawiać się, czy użyć quack() Czy bark(), czy nawet określić typ przed wysłaniem poprawnej Wiadomości do obiektu.

 6
Author: 太極者無極而生,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 04:11:31

Aby dodać do istniejących postów, czasami kodowanie interfejsów pomaga w dużych projektach, gdy deweloperzy pracują jednocześnie nad oddzielnymi komponentami. Wszystko, czego potrzebujesz, to definiowanie interfejsów z góry i pisanie do nich kodu, podczas gdy inni programiści piszą kod do interfejsu, który implementujesz.

 4
Author: edgi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 01:08:55

Jest to również dobre dla testów jednostkowych, można wprowadzić własne klasy (które spełniają wymagania interfejsu) do klasy, która od niego zależy

 4
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-08 21:12:54

Tak więc, aby to dobrze zrozumieć, zaletą interfejsu jest to, że mogę oddzielić wywołanie metody od konkretnej klasy. Zamiast tego tworzymy instancję interfejsu, gdzie implementacja jest podawana z dowolnej klasy, którą wybieram, która implementuje ten interfejs. Pozwala mi to na posiadanie wielu klas, które mają podobną, ale nieco inną funkcjonalność i w niektórych przypadkach (sprawy związane z intencją interfejsu) nie dbają o to, który obiekt to jest.

Dla przykład, mógłbym mieć interfejs ruchu. Metoda, która sprawia, że coś "porusza się" i każdy obiekt (osoba, samochód, kot), który implementuje interfejs ruchu, może zostać przekazany i poproszony o ruch. Bez metody każdy zna typ klasy.

 3
Author: Damien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 22:05:50

Wyobraź sobie, że masz produkt o nazwie "Zebra", który można rozszerzyć za pomocą wtyczek. Znajduje wtyczki, wyszukując biblioteki DLL w jakimś katalogu. Ładuje wszystkie biblioteki DLL i używa reflection, aby znaleźć klasy implementujące IZebraPlugin, a następnie wywołuje metody tego interfejsu, aby komunikować się z wtyczkami.

To czyni go całkowicie niezależnym od żadnej konkretnej klasy wtyczki - nie obchodzi go, jakie są klasy. Dba tylko o to, aby spełniały specyfikację interfejsu.

Interfejsy są sposobem definiowania punktów rozszerzalności w ten sposób. Kod, który rozmawia z interfejsem, jest luźniej sprzężony - w rzeczywistości nie jest w ogóle sprzężony z żadnym innym konkretnym kodem. Może współpracować z wtyczkami napisanymi wiele lat później przez osoby, które nigdy nie spotkały się z oryginalnym deweloperem.

Możesz zamiast tego użyć klasy bazowej z funkcjami wirtualnymi - wszystkie wtyczki wywodzą się z klasy bazowej. Ale jest to znacznie bardziej ograniczające, ponieważ klasa może mieć tylko jedną bazę klasy, natomiast może zaimplementować dowolną liczbę interfejsów.

 3
Author: Daniel Earwicker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-27 14:15:25

Wyjaśnienie C++.

Pomyśl o interfejsie jako o publicznych metodach klas.

Można wtedy utworzyć szablon, który "zależy" od tych publicznych metod w celu wykonania własnej funkcji (powoduje wywołania funkcji zdefiniowane w klasach public interface). Powiedzmy, że ten szablon jest kontenerem, jak Klasa wektorowa, A Interfejs, od którego zależy, to algorytm wyszukiwania.

Każda klasa algorytmu, która definiuje funkcje / wektor interfejsu, do której wywołania "umowa" (jak ktoś wyjaśnił w oryginalnej odpowiedzi). Algorytmy nie muszą nawet należeć do tej samej klasy bazowej; jedynym wymogiem jest to, że funkcje/metody, od których zależy Wektor (interfejs) są zdefiniowane w algorytmie.

Chodzi o to, że możesz dostarczyć dowolny inny algorytm/klasę Wyszukiwania, o ile dostarczy interfejs, od którego zależy Wektor (wyszukiwanie bańkowe, wyszukiwanie sekwencyjne, szybkie wyszukiwanie).

Możesz też zaprojektować inne kontenery (listy, kolejki), które wykorzystywałyby ten sam algorytm wyszukiwania co Vector, dzięki temu, że spełniają interfejs/kontrakt, od którego zależą Twoje algorytmy wyszukiwania.

To oszczędza czas (zasada OOP 'code reuse'), ponieważ jesteś w stanie napisać algorytm raz zamiast raz i raz i raz dla każdego nowego obiektu, który tworzysz, bez nadmiernego komplikowania problemu z zarośniętym drzewem dziedziczenia.

Co do "pominięcia" tego, jak rzeczy działają; big-time (przynajmniej w C++), gdyż tak działa większość frameworku biblioteki szablonów standardowych.

Oczywiście przy użyciu klas dziedziczenia i abstrakcyjnych metodologia programowania do interfejsu się zmienia; ale zasada jest taka sama, Twoje publiczne funkcje/metody są twoim interfejsem klas.

To ogromny temat i jedna z podstawowych zasad wzorców projektowych.

 3
Author: Trae Barlow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 22:52:53

W Javie te konkretne klasy implementują interfejs CharSequence:

CharBuffer, String, StringBuffer, StringBuilder

Te konkretne klasy nie mają wspólnej klasy nadrzędnej innej niż obiekt, więc nie ma nic, co je łączy, poza faktem, że każda z nich ma coś wspólnego z tablicami znaków, reprezentującymi takie lub manipulującymi takimi. Na przykład, znaki String nie mogą być zmieniane po utworzeniu instancji obiektu String, natomiast znaki StringBuffer lub StringBuilder mogą być edytowane.

Jednak każda z tych klas jest w stanie odpowiednio zaimplementować metody interfejsu CharSequence:

char charAt(int index)
int length()
CharSequence subSequence(int start, int end)
String toString()

W niektórych przypadkach klasy biblioteki klas Java, które akceptowały ciąg znaków, zostały zmienione tak, aby teraz akceptowały interfejs CharSequence. Więc jeśli masz instancję StringBuilder, zamiast wyodrębniać obiekt String (co oznacza utworzenie nowej instancji obiektu), możesz po prostu przekazać Sam StringBuilder implementuje interfejs CharSequence.

Rozszerzalny interfejs implementowany przez niektóre klasy ma podobne korzyści w każdej sytuacji, w której znaki mogą być dołączane do instancji konkretnego obiektu klasy. Wszystkie te konkretne klasy implementują dodatek do interfejsu:

Buforedwriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, StringWriter, Writer

 2
Author: RogerV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-21 04:17:54

W prostych słowach... Jeśli piszę nową klasę Swimmer, aby dodać funkcjonalność swim () i muszę użyć obiektu klasy say Dog, a ta klasa Dog implementuje interfejs Animal, który deklaruje swim () [aby lepiej zrozumieć...możesz narysować diagram, o czym mówię]. Na szczycie hierarchii (zwierzę) jest bardzo abstrakcyjny, podczas gdy na dole (pies) jest bardzo konkretny. Sposób, w jaki myślę o "programowaniu do interfejsów" jest taki, że jak piszę, chcę napisać swój kod przeciwko interfejsowi, który jest tak wysoko w hierarchii, która w tym przypadku jest obiektem zwierzęcym. Interfejs jest wolny od szczegółów implementacji, co sprawia, że kod jest luźno powiązany. Szczegóły implementacji mogą być zmieniane z czasem, jednak nie wpłynie to na pozostały Kod, ponieważ wszystko, co wchodzi w interakcję, to interfejs, a nie implementacja. Nie obchodzi cię, jak wygląda realizacja...wszystko, co wiesz, to to, że będzie klasa, która wdrożyłaby interfejs.

 2
Author: Abhishek Shrivastava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-28 16:44:22

Krótka historia: Listonosz jest proszony o powrót do domu po domu i odebranie okładek (listów,dokumentów, czeków, Karty Podarunkowej, aplikacji,loveletter) z wypisanym adresem do doręczenia.

Przypuśćmy, że nie ma przykrywki i poproś listonosza, aby poszedł do domu po domu i odebrał wszystkie rzeczy i dostarczył innej osobie listonosz może się pomylić.]} [[16]}so better owinąć go okładką (w naszej historii jest to interfejs) wtedy zrobi swoją pracę dobrze.

Teraz listonosz ma otrzymać i dostarczaj tylko pokrowce..(nie przejmował się tym, co jest w okładce).

Utwórz typ interface nie rzeczywisty typ, ale zaimplementuj z rzeczywistym typem.

Create to interface oznacza, że Twoje komponenty łatwo dopasowują się do reszty kodu

Daję ci przykład.

Masz interfejs samolotu, jak poniżej.

interface Airplane{
    parkPlane();
    servicePlane();
}

Załóżmy, że masz metody w klasie kontrolerów płaszczyzn takich jak

parkPlane(Airplane plane)

I

servicePlane(Airplane plane)

Zaimplementowane w Twoim program. To nie złamie Twojego kodu. Nie musi się zmieniać, dopóki przyjmuje argumenty jako AirPlane.

Ponieważ zaakceptuje każdy samolot pomimo rzeczywistego typu, flyer, highflyr, fighter, itd.

Także w zbiorze:

List<Airplane> plane; // zabierze wszystkie wasze samoloty.

Poniższy przykład oczyści twoje zrozumienie.


Masz samolot myśliwski, który go implementuje, więc

public class Fighter implements Airplane {

    public void  parkPlane(){
        // Specific implementations for fighter plane to park
    }
    public void  servicePlane(){
        // Specific implementatoins for fighter plane to service.
    }
}

To samo dla Highflyera i inne klasy:

public class HighFlyer implements Airplane {

    public void  parkPlane(){
        // Specific implementations for HighFlyer plane to park
    }

    public void  servicePlane(){
        // specific implementatoins for HighFlyer plane to service.
    }
}

Pomyśl teraz, że Twoje klasy kontrolerów używają AirPlane kilka razy,

Załóżmy, że twoja klasa kontrolera to ControlPlane jak poniżej,

public Class ControlPlane{ 
 AirPlane plane;
 // so much method with AirPlane reference are used here...
}

Here magic comes as

Możesz tworzyć nowe AirPlane instancje typu tyle ile chcesz i nie zmieniasz

Kod klasy ControlPlane.

Możesz dodać instancję..

JumboJetPlane // implementing AirPlane interface.
AirBus        // implementing AirPlane interface.

Możesz usunąć instancje.. również wcześniej utworzonych typów.

 2
Author: Sanjay Rabari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-08 10:42:54

Q: -... "Możesz użyć dowolnej klasy, która implementuje interfejs?"
- Tak.

Q: -... "Kiedy miałbyś to zrobić?"
O: - za każdym razem, gdy potrzebujesz klasy, która implementuje interfejs(y).

Uwaga: nie możemy utworzyć instancji interfejsu nie zaimplementowanego przez klasę - prawda.

    Dlaczego?
  • ponieważ interfejs ma tylko prototypy metod, a nie definicje (tylko nazwy funkcji, nie ich logika)

AnIntf anInst = new Aclass ();
// moglibyśmy to zrobić Tylko jeśli Aclass implementuje AnIntf.
// anInst będzie miał odniesienie Aclass.


Uwaga:
teraz możemy zrozumieć, co się stanie, jeśli Bclass i Cclass implementują ten sam Dintf.

Dintf bInst = new Bclass();  
// now we could call all Dintf functions implemented (defined) in Bclass.

Dintf cInst = new Cclass();  
// now we could call all Dintf functions implemented (defined) in Cclass.

Co mamy:
te same prototypy interfejsu (nazwy funkcji w interfejsie) i wywołują różne wdrożenia.

Bibliografia:
prototypy-wikipedia

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-09 06:53:31

Interface jest jak contract, gdzie chcesz, aby Twoja klasa implementacji zaimplementowała metody napisane w contract (Interface).Ponieważ java nie zapewnia dziedziczenia wielokrotnego, programowanie interfejsu jest dobrym sposobem na osiągnięcie celu dziedziczenia wielokrotnego.Jeśli masz klasę A, która już rozszerza inną klasę B, ale chcesz, aby Klasa A również postępowała zgodnie z pewnymi wytycznymi lub wdrożyła określony kontrakt, możesz to zrobić poprzez Programowanie strategii interfejsu.

 1
Author: Shivam Sugandhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-27 10:44:19

Korzystne może być programowanie interfejsów, nawet jeśli nie jesteśmy zależni od abstrakcji.

Programowanie do interfejsów zmusza nas do użycia kontekstowo odpowiedniego podzbioru obiektu. to pomaga, bo to:

  1. uniemożliwia nam robienie niewłaściwych kontekstowo rzeczy i
  2. pozwala nam bezpiecznie zmienić implementację w przyszłości.

Na przykład, rozważmy klasę Person, która implementuje Friend i Employee interfejs.

class Person implements AbstractEmployee, AbstractFriend {

}

W kontekście urodzin danej osoby, programujemy do interfejsu Friend, Aby zapobiec traktowaniu osoby jak Employee.

function party() {
    const friend: Friend = new Person("Kathryn");
    friend.HaveFun();
}

W kontekście pracy danej osoby, programujemy do interfejsu Employee, aby zapobiec rozmyciu granic miejsca pracy.

function workplace() {
    const employee: Employee = new Person("Kathryn");
    employee.DoWork();
}
Świetnie. Zachowywaliśmy się odpowiednio w różnych kontekstach, a nasze oprogramowanie działa dobrze.

Daleko w przyszłość, jeśli nasz biznes zmieni się na pracę z psami, możemy zmienić oprogramowanie dość łatwo. Najpierw tworzymy klasę Dog, która implementuje zarówno Friend, jak i Employee. Następnie bezpiecznie zmieniamy new Person() na new Dog(). Nawet jeśli obie funkcje mają tysiące linii kodu, ta prosta edycja będzie działać, ponieważ wiemy, że następujące są prawdziwe: {]}

  1. funkcja party używa tylko Friend podzbioru Person.
  2. funkcja workplace używa tylko Employee podzbioru Person.
  3. Klasa Dog implementuje zarówno interfejsy Friend, jak i Employee.

Na z drugiej strony, jeśli party lub workplace miałyby być zaprogramowane przeciwko Person, istnieje ryzyko, że oba mają kod specyficzny dla Person. Zmiana z Person na Dog wymagałaby przeczesania kodu w celu wytępienia dowolnego kodu Person specyficznego dla Dog, który nie obsługuje.

Morał : programowanie interfejsów pomaga naszemu kodowi zachowywać się właściwie i być gotowym na zmiany. Przygotowuje również nasz kod do polegania na abstrakcjach, co przynosi jeszcze więcej korzyści.

 1
Author: Shaun Luttin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-03 21:10:38

Również widzę tutaj wiele dobrych i wyjaśniających odpowiedzi, więc chcę tutaj podać mój punkt widzenia, w tym kilka dodatkowych informacji, co zauważyłem przy użyciu tej metody.

Testy jednostkowe

Przez ostatnie dwa lata pisałem projekt hobbystyczny i nie pisałem do niego testów jednostkowych. Po napisaniu około 50k linii okazało się, że naprawdę konieczne będzie napisanie testów jednostkowych. Nie korzystałem z interfejsów (lub bardzo oszczędnie)... i kiedy zrobiłem mój pierwszy test jednostkowy, znalazłem to było skomplikowane. Dlaczego?

Ponieważ musiałem zrobić wiele instancji klas, używanych do wprowadzania jako zmienne klasy i/lub parametry. Tak więc testy wyglądają bardziej jak testy integracyjne(trzeba stworzyć kompletny "framework" klas, ponieważ wszystkie były ze sobą powiązane).

Strach przed interfejsami Postanowiłem więc użyć interfejsów. Obawiałem się, że musiałem wielokrotnie implementować wszystkie funkcjonalności wszędzie (we wszystkich używanych klasach). W pewnym sensie jest to jednak prawdą, stosując dziedziczenie można go znacznie zmniejszyć.

Połączenie interfejsów i dziedziczenia Okazało się, że połączenie jest bardzo dobre do stosowania. Podaję bardzo prosty przykład.

public interface IPricable
{
    int Price { get; }
}

public interface ICar : IPricable

public abstract class Article
{
    public int Price { get { return ... } }
}

public class Car : Article, ICar
{
    // Price does not need to be defined here
}

W ten sposób kopiowanie kodu nie jest konieczne, przy jednoczesnym korzystaniu z samochodu jako interfejsu (ICar).

 0
Author: Michel Keijzers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-18 13:23:31

Zacznijmy od kilku definicji:

Interfejs n. zbiór wszystkich sygnatur zdefiniowanych przez operacje obiektu jest nazywany interfejsem do obiektu

Typ n. a specific interface

Prostym przykładem interfejsu zdefiniowanego powyżej byłyby wszystkie metody obiektów PDO, takie jak query(), commit(), close() itd., jako całość, nie osobno. Metody te, tj. jego interfejs określa kompletny zestaw wiadomości, żądań, które mogą być wysłane do obiektu.

A typ zdefiniowany powyżej jest konkretnym interfejsem. Użyję interfejsu make-up shape do zademonstrowania: draw(), getArea(), getPerimeter() itd..

Jeśli obiekt jest typu bazy danych, to znaczy, że akceptuje wiadomości / żądania interfejsu bazy danych, query(), commit() itd.. Obiekty mogą być wielu typów. Obiekt bazy danych może być typu shape, o ile implementuje on jego interfejs, w którym to przypadku będzie to sub-typing .

Wiele obiektów może mieć wiele różnych interfejsów/typów i implementować ten interfejs w różny sposób. To pozwala nam zastępować przedmioty, pozwalając nam wybrać, który z nich użyć. Znany również jako polimorfizm.

Klient będzie świadomy tylko interfejsu, a nie implementacji.

Więc w istocie Programowanie do interfejsu wiązałoby się z utworzeniem pewnego rodzaju klasy abstrakcyjnej, takiej jak Shape z interfejs tylko określony tzn. draw(), getCoordinates(), getArea() itd.. A następnie mają różne konkretne klasy zaimplementować te interfejsy, takie jak Klasa Circle, Klasa Square, Klasa Triangle. stąd program do interfejsu, a nie implementacji.

 0
Author: Robert Rocha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-05 23:48:47

Program do interfejsu pozwala bezproblemowo zmieniać realizację kontraktu zdefiniowanego przez interfejs. Pozwala to na luźne powiązanie pomiędzy kontraktem a konkretnymi realizacjami.

IInterface classRef = new ObjectWhatever()

Możesz użyć dowolnej klasy, która implementuje IInterface? Kiedy miałbyś to zrobić?

Spójrz na to pytanie SE na dobry przykład.

Dlaczego powinien być preferowany interfejs dla klasy Java?

Robi za pomocą Interfejs hit wydajność?

Jeśli tak, to ile?
Tak. Będzie miał niewielką wydajność nad głową w sub-sekundach. Jeśli jednak Twoja aplikacja wymaga dynamicznej zmiany implementacji interfejsu, nie martw się o wpływ na wydajność.

Jak można tego uniknąć bez konieczności utrzymywania dwóch bitów kodu?

Nie staraj się unikać wielu implementacji interfejsu, jeśli aplikacja ich potrzebuje. W przypadku braku szczelnego sprzężenia interfejs z jedną konkretną implementacją, być może trzeba będzie wdrożyć łatkę, aby zmienić jedną implementację na inną.

Jeden dobry przypadek użycia: implementacja wzorca strategii:

Przykład wzorca strategii w świecie rzeczywistym

 0
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-25 13:31:33

Nie zachowuję interfaces są najważniejszą rzeczą w języku: częściej używa się klasy dziedziczącej. Ale w każdym razie są ważne!
na przykład (jest to kod Java, ale może po prostu dostosować się do C# lub wielu innych języków):

interface Convertable<T> {

    T convert();
}

public class NumerableText implements Convertable<Integer> {

    private String text = "";

    public NumerableText() { }

    public NumerableText(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Integer convert() {
        return this.text.hashCode();
    }
}

public class NumerableTextArray implements Convertable<Integer> {

    private String[] textArray = "";

    public NumerableTextArray() { }

    public NumerableTextArray(String[] textArray) {
        this.textArray = textArray;
    }

    public String[] getTextArray() {
        return this.textArray;
    }

    public void setTextArray(String[] text) {
        this.textArray = textArray;
    }

    public Integer convert() {
        Integer value = 0;
        for (String text : textArray)
            value += text.hashCode();
        return value;
    }
}

public class Foo {

    public static void main() {
        Convertable<Integer> num1 = new NumerableText("hello");
        Convertable<Integer> num2 = new NumerableTextArray(new String[] { "test n°1", "test n°2" });
        System.out.println(String.valueOf(num1.convert()));
        System.out.println(String.valueOf(num2.convert()));
        //Here are you two numbers generated from two classes of different type, but both with the method convert(), which allows you to get that number.
    }
}
 0
Author: Davide Cannizzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-04 14:55:57

Program do interfejsu oznacza, że nie dostarczaj twardych kodów w odpowiedni sposób, oznacza, że Twoje kody powinny zostać rozszerzone bez naruszania poprzedniej funkcjonalności..... just extensions not editing the prev codes

 0
Author: ndoty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 15:55:21