Jaki jest sens interfejsów w PHP?

224

Interfejsy pozwalają tworzyć kod definiujący metody klas, które go implementują. Nie można jednak dodać żadnego kodu do tych metod.

Klasy abstrakcyjne pozwalają robić to samo, dodając kod do metody.

Skoro możesz osiągnąć ten sam cel za pomocą klas abstrakcyjnych, dlaczego w ogóle potrzebujemy koncepcji interfejsów?

Powiedziano mi, że ma to związek z teorią OO od C ++ do Javy, na której oparte są rzeczy związane z OO PHP. Czy koncepcja jest przydatna w Javie, ale nie w PHP? Czy to tylko sposób na powstrzymanie się od wypełniania symboli zastępczych w klasie abstrakcyjnej? Czy coś brakuje?

mk.
źródło
4
Musisz to przeczytać: stackoverflow.com/a/384067/14673
Luc M
całkiem pewna, że ​​to pomoc psychiczna i pomoc komunikacyjna. Interfejsy działają jako doskonałe narzędzia edukacyjne dla interfejsu API, ponieważ łączą w sobie usługi, które interfejs API udostępnia razem w abstrakcyjny sposób, który można odczytać bez wiedzy o implementacji. Jest to drogie, ale ponieważ ludzie, którzy czują się komfortowo z interfejsem, mogą już korzystać z funkcji bezpośrednio, bez potrzeby korzystania z klas, oszczędzając w ten sposób wskaźnik. bez interfejsów zdefiniowanych dla języka może być trudne planowanie z wyprzedzeniem dla wielu programistów, ponieważ ludzie przyzwyczajeni do „przerywania języków” często wolą projektować z interfejsami niż na papierze.
Dmitry

Odpowiedzi:

142

Głównym celem interfejsów jest zapewnienie elastyczności zmuszania klasy do implementacji wielu interfejsów, ale nadal nie zezwalają na wielokrotne dziedziczenie. Problemy z dziedziczeniem z wielu klas są liczne i zróżnicowane, a wikipedia strona na ich temat całkiem dobrze je podsumowuje.

Interfejsy to kompromis. Większość problemów z wielokrotnym dziedziczeniem nie dotyczy abstrakcyjnych klas bazowych, więc większość współczesnych języków wyłącza wielokrotne dziedziczenie, ale wywołuje interfejsy abstrakcyjnych klas bazowych i pozwala klasie „zaimplementować” tyle z nich, ile chcą.

Craig H.
źródło
39
Można również powiedzieć, że * Interfejsy zapewniają projekt dla klasy z zerową implementacją. * Klasy abstrakcyjne zapewniają pewien projekt, z pewną implementacją. Klasy abstrakcyjne są najbardziej przydatne, gdy klasy potomne mają pewne podobieństwa implementacyjne, ale różnią się w niektórych implementacjach.
Jrgns,
@Craig, Nie ma nieodłącznego problemu z wielokrotnym dziedziczeniem, tylko że obecne języki nie są wystarczająco mocne, aby poprawnie je wdrożyć. „Problemy” można w rzeczywistości dość łatwo naprawić, na przykład określenie wyraźnej ścieżki dziedziczenia dla funkcji odziedziczonych o tej samej nazwie może rozwiązać dylemat diamentu.
Pacerier
15
W ogóle nie o to chodzi w interfejsach. Nie jest to kompromis w sprawie wielokrotnego dziedziczenia, chodzi o stworzenie konceptualnej i abstrakcyjnej umowy dla obiektów do wdrożenia oraz dla innych obiektów / metod do wykorzystania. interfejsy są narzędziem do polimorfizmu, a nie do bezpośredniego dziedziczenia.
Duch Madary
123

Ta koncepcja jest przydatna w programowaniu obiektowym. Dla mnie myślę o interfejsie jako umowie. Tak długo, jak moja klasa i twoja klasa zgadzają się na podpisanie umowy na tę metodę, możemy „interfejsu”. Jeśli chodzi o klasy abstrakcyjne, to te, które widzę jako bardziej podstawowe klasy, które usuwają niektóre metody i muszę uzupełnić szczegóły.

John Downey
źródło
To sprawiło, że trochę to zrozumiałem. To tak, jak w przypadku przestrzeni nazw - dzięki czemu wspólny kod jest łatwiejszy w użyciu i bez konfliktów. Łatwiej jest, gdy dwie osoby prowadzą zajęcia na tej samej bazie, prawda?
RedClover
Czy nie musimy odróżniać ogólnej koncepcji „interfejsu” od konkretnych interfejsów w języku takim jak PHP? Na przykład każda funkcja ma „interfejs”, który określa sposób korzystania z niej i ukrywa jej implementację. Tak więc taki „umowny” interfejs nie wymaga specjalnej funkcji językowej. Dlatego funkcja języka musi dotyczyć czegoś innego (lub czegoś dodatkowego).,
UuDdLrLrSs
70

Dlaczego potrzebujesz interfejsu, jeśli istnieją już abstrakcyjne klasy? Aby zapobiec wielokrotnemu dziedziczeniu (może powodować wiele znanych problemów).

Jeden z takich problemów:

„Problem diamentów” (czasem określany jako „śmiertelny diament śmierci”) jest dwuznacznością, która pojawia się, gdy dwie klasy B i C dziedziczą po A, a klasa D dziedziczy zarówno po B, jak i C. Jeśli istnieje metoda w A, która B i C zostały zastąpione, a D nie zastępuje go, to którą wersję metody dziedziczy D: wersję B, czy wersję C?

Źródło: https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem

Dlaczego / Kiedy korzystać z interfejsu? Przykład ... Wszystkie samochody na świecie mają ten sam interfejs (metody) ... AccelerationPedalIsOnTheRight(),BrakePedalISOnTheLeft() . Wyobraź sobie, że każda marka samochodów miałaby te „metody” inne niż inna marka. BMW miałoby Hamulce po prawej stronie, a Honda miałaby hamulce po lewej stronie koła. Ludzie będą musieli nauczyć się, jak działają te „metody” za każdym razem, gdy kupują inną markę samochodu. Dlatego dobrze jest mieć ten sam interfejs w wielu „miejscach”.

Co robi dla ciebie interfejs (dlaczego ktoś miałby go używać)? Interfejs zapobiega popełnianiu „błędów” (zapewnia, że ​​wszystkie klasy, które implementują określony interfejs, będą miały wszystkie metody dostępne w interfejsie).

// Methods inside this interface must be implemented in all classes which implement this interface.
interface IPersonService
{   
    public function Create($personObject);
}

class MySqlPerson implements IPersonService
{
    public function Create($personObject)
    {
        // Create a new person in MySql database.
    }
}

class MongoPerson implements IPersonService
{
    public function Create($personObject)
    {
        // Mongo database creates a new person differently then MySQL does. But the code outside of this method doesn't care how a person will be added to the database, all it has to know is that the method Create() has 1 parameter (the person object).
    }
}

W ten sposób Create()metoda będzie zawsze używana w ten sam sposób. Nie ma znaczenia, czy korzystamy z MySqlPersonklasy, czy zMongoPerson klasy. Sposób w jaki korzystamy z metody pozostaje taki sam (interfejs pozostaje taki sam).

Na przykład będzie używany w ten sposób (wszędzie w naszym kodzie):

new MySqlPerson()->Create($personObject);
new MongoPerson()->Create($personObject);

W ten sposób coś takiego nie może się wydarzyć:

new MySqlPerson()->Create($personObject)
new MongoPerson()->Create($personsName, $personsAge);

O wiele łatwiej jest zapamiętać jeden interfejs i używać wszędzie tego samego interfejsu, niż wielu różnych.

W ten sposób wnętrze Create()metody może być różne dla różnych klas, bez wpływu na kod „zewnętrzny”, który wywołuje tę metodę. Cały zewnętrzny kod musi wiedzieć, że metoda Create()ma 1 parametr ( $personObject), ponieważ w ten sposób zewnętrzny kod użyje / wywoła metodę. Zewnętrzny kod nie obchodzi, co dzieje się w metodzie; musi tylko wiedzieć, jak go użyć / nazwać.

Możesz to zrobić także bez interfejsu, ale jeśli używasz interfejsu, jest on „bezpieczniejszy” (ponieważ zapobiega popełnianiu błędów). Interfejs zapewnia, że ​​metoda Create()będzie miała tę samą sygnaturę (te same typy i tę samą liczbę parametrów) we wszystkich klasach, które implementują interfejs. W ten sposób możesz być pewien, że DOWOLNA klasa, która implementuje IPersonServiceinterfejs, będzie miała metodę Create()(w tym przykładzie) i będzie potrzebowała tylko 1 parametru ( $personObject) do wywołania / użycia.

Klasa implementująca interfejs musi implementować wszystkie metody, które interfejs wykonuje / posiada.

Mam nadzieję, że nie powtórzyłem się zbyt często.

Jo Smo
źródło
Naprawdę fajna analogia do pedałów samochodowych!
James
24

Różnica między używaniem interfejsu a klasą abstrakcyjną ma dla mnie więcej wspólnego z organizacją kodu niż z wymuszaniem przez sam język. Używam ich często podczas przygotowywania kodu dla innych programistów do pracy, aby pozostawali w zamierzonych wzorcach projektowych. Interfejsy są rodzajem „projektu na podstawie umowy”, w którym kod zgadza się odpowiadać na określony zestaw wywołań API, które mogą pochodzić z kodu, do którego nie masz dostępu.

Podczas gdy dziedziczenie po klasie abstrakcyjnej jest relacją „jest”, nie zawsze jest to, czego chcesz, a implementacja interfejsu jest bardziej relacją „działa jak”. Różnica ta może być dość znacząca w niektórych kontekstach.

Załóżmy na przykład, że masz konto klasy abstrakcyjnej, z którego korzysta wiele innych klas (typy kont i tak dalej). Ma określony zestaw metod, które można zastosować tylko do tej grupy typów. Jednak niektóre z tych podklas kont implementują Versionable, Listable lub Editable, dzięki czemu można je wrzucić do kontrolerów, które oczekują używania tych interfejsów API. Kontroler nie dba o to, jaki to obiekt

Z drugiej strony, mogę również utworzyć obiekt, który nie rozciąga się na konto, powiedzmy klasę abstrakcyjną użytkownika, i nadal implementuję możliwość wyświetlania i edycji, ale nie wersji, co nie ma tutaj sensu.

W ten sposób mówię, że podklasa FooUser NIE jest kontem, ale NIE działa jak obiekt edytowalny. Podobnie BarAccount obejmuje konto, ale nie jest podklasą użytkownika, ale implementuje edytowalność, możliwość wyświetlania i również wersję.

Dodanie wszystkich tych interfejsów API dla edycji, listy i wersji do samych klas abstrakcyjnych byłoby nie tylko zaśmiecone i brzydkie, ale albo powieliłoby wspólne interfejsy konta i użytkownika, albo zmusiłoby mój obiekt użytkownika do implementacji wersji, prawdopodobnie tylko do rzucenia wyjątek.

Sam McAfee
źródło
To jest właśnie tutaj. Rygorystycznie zmuszaj programistów do korzystania z twoich metod bez ich rozszerzania lub nadpisywania
Nick
21

Interfejsy są zasadniczo planem tego, co możesz stworzyć. Definiują metody, które musi mieć klasa , ale można tworzyć dodatkowe metody poza tymi ograniczeniami.

Nie jestem pewien, co masz na myśli mówiąc, że nie możesz dodać kodu do metod - bo możesz. Czy stosujesz interfejs do klasy abstrakcyjnej czy klasy, która ją rozszerza?

Metoda interfejsu zastosowana do klasy abstrakcyjnej będzie musiała zostać zaimplementowana w tej klasie abstrakcyjnej. Jednak zastosuj ten interfejs do klasy rozszerzającej, a metoda wymaga jedynie implementacji w klasie rozszerzającej. Mogę się tutaj mylić - nie używam interfejsów tak często, jak powinienem / powinienem.

Zawsze uważałem interfejsy za wzorzec dla zewnętrznych programistów lub dodatkowy zestaw reguł zapewniający poprawność.

Ross
źródło
9
W PHP interfejsy zawierają tylko deklarację metody, a nie rzeczywistą implementację. Klasy abstrakcyjne pozwalają jednak „dodawać kod” do metod dziedziczonych przez klasy, które go rozszerzają. Wierzę, że ta różnica dotyczy właśnie tego mk.
nocash
13

Będziesz używać interfejsów w PHP:

  1. Aby ukryć implementację - ustal protokół dostępu do klasy obiektów i zmień implementację bazową bez refaktoryzacji we wszystkich miejscach, w których korzystałeś z tych obiektów
  2. Aby sprawdzić typ - upewnij się, że parametr ma określony typ $object instanceof MyInterface
  3. Aby wymusić sprawdzanie parametrów w czasie wykonywania
  4. Aby zaimplementować wiele zachowań w jednej klasie (buduj typy złożone)

    klasa Car implementuje EngineInterface, BodyInterface, SteeringInterface {

tak, że Carteraz obiekt ca start(), stop()(EngineInterface) lub goRight(), goLeft()(Interfejs sterowania )

i inne rzeczy, o których nie mogę teraz myśleć

Numer 4 to prawdopodobnie najbardziej oczywisty przypadek użycia, którego nie można rozwiązać za pomocą klas abstrakcyjnych.

Z myślenia w Javie:

Interfejs mówi: „Tak będą wyglądały wszystkie klasy, które implementują ten konkretny interfejs”. Zatem każdy kod korzystający z określonego interfejsu wie, jakie metody można wywołać dla tego interfejsu i to wszystko. Interfejs służy więc do ustanowienia „protokołu” między klasami.

catalin.costache
źródło
10

Interfejsy istnieją nie jako podstawa do rozszerzania klas, ale jako mapa wymaganych funkcji.

Oto przykład użycia interfejsu, w którym klasa abstrakcyjna nie pasuje:
Załóżmy, że mam aplikację kalendarza, która pozwala użytkownikom importować dane kalendarza ze źródeł zewnętrznych. Pisałbym klasy do obsługi importowania każdego typu źródła danych (ical, rss, atom, json) Każda z tych klas wdrożyłaby wspólny interfejs, który zapewniłby, że wszystkie mają wspólne metody publiczne, których potrzebuje moja aplikacja do uzyskania danych.

<?php

interface ImportableFeed 
{
    public function getEvents();
}

Następnie, gdy użytkownik doda nowy kanał, mogę zidentyfikować typ kanału i użyć klasy opracowanej dla tego typu, aby zaimportować dane. Każda klasa napisana w celu zaimportowania danych dla określonego kanału miałaby zupełnie inny kod, w przeciwnym razie może być bardzo niewiele podobieństw między klasami poza tym, że są one wymagane do wdrożenia interfejsu, który pozwala mojej aplikacji na ich wykorzystanie. Gdybym miał użyć klasy abstrakcyjnej, bardzo łatwo mogłem zignorować fakt, że nie przesłoniłem metody getEvents (), która następnie zepsułaby moją aplikację w tym przypadku, natomiast użycie interfejsu nie pozwoliłoby na uruchomienie mojej aplikacji, gdyby ŻADNA z metod zdefiniowane w interfejsie nie istnieją w klasie, która go zaimplementowała. Moja aplikacja nie musi dbać o to, jakiej klasy używa do pobierania danych z kanału,

Aby pójść o krok dalej, interfejs okazuje się niezwykle przydatny, gdy wracam do aplikacji kalendarza z zamiarem dodania innego rodzaju kanału. Korzystanie z interfejsu ImportableFeed oznacza, że ​​mogę kontynuować dodawanie kolejnych klas, które importują różne typy plików danych, po prostu dodając nowe klasy, które implementują ten interfejs. To pozwala mi dodawać mnóstwo funkcji bez konieczności dodawania niepotrzebnie dużej ilości do mojej podstawowej aplikacji, ponieważ moja podstawowa aplikacja opiera się tylko na dostępnych publicznych metodach wymaganych przez interfejs, o ile moje nowe klasy importu kanałów implementują interfejs ImportableFeed, a następnie I wiem, że mogę po prostu go upuścić i kontynuować ruch.

To tylko bardzo prosty początek. Następnie mogę utworzyć inny interfejs, do którego wdrożenia będą wymagane wszystkie moje klasy kalendarza, który oferuje więcej funkcji specyficznych dla typu pliku danych, który obsługuje klasa. Innym dobrym przykładem może być metoda weryfikacji typu pliku danych itp.

To wykracza poza pytanie, ale ponieważ użyłem powyższego przykładu: interfejsy mają własny zestaw problemów, jeśli są używane w ten sposób. Uważam, że muszę upewnić się, że dane wyjściowe są zwracane z metod zaimplementowanych w celu dopasowania interfejsu. Aby to osiągnąć, używam środowiska IDE, które odczytuje bloki PHPDoc, i dodam typ zwracany jako podpowiedź do typu w bloku PHPDoc interfejsu, który następnie przetłumacz na konkretną klasę, która go implementuje. Moje klasy, które wykorzystują dane wyjściowe z klas implementujących ten interfejs, będą przynajmniej wiedziały, że oczekuje tablicy zwróconej w tym przykładzie:

<?php
interface ImportableFeed 
{
    /**
     * @return array
     */
    public function getEvents();
}

Nie ma wiele miejsca na porównanie klas abstrakcyjnych i interfejsów. Interfejsy to po prostu mapy, które po zaimplementowaniu wymagają, aby klasa miała zestaw interfejsów publicznych.

Houghtelin
źródło
Dobre wyjaśnienie :) Dzięki!
Razvan.432
Aby dodać informacje: w klasie abstrakcyjnej, jeśli deklarujesz metodę jako abstrakcyjną, zachowuje się ona jak interfejs, więc nie możesz zignorować faktu, że nie przesłaniałeś metody getEvents (). Aplikacja ulegnie awarii w taki sam sposób, jak w przypadku interfejsu.
Rikudou_Sennin
8

Interfejsy służą nie tylko do upewnienia się, że programiści wdrażają określone metody. Chodzi o to, że ponieważ gwarantuje się, że klasy te posiadają pewne metody, możesz z nich korzystać, nawet jeśli nie znasz faktycznego typu klasy. Przykład:

interface Readable {
  String read();
}

List<Readable> readables; // dunno what these actually are, but we know they have read();
for(Readable reader : readables)
  System.out.println(reader.read());

W wielu przypadkach nie ma sensu przedstawianie klasy bazowej, abstrakcyjnej czy nie, ponieważ implementacje różnią się znacznie i nie współużytkują niczego oprócz kilku metod.

Języki o typie dynamicznym mają pojęcie „kaczego pisma”, w którym nie potrzebujesz interfejsów; możesz założyć, że obiekt ma wywoływaną metodę. To rozwiązuje problem w językach o typie statycznym, w których Twój obiekt ma jakąś metodę (w moim przykładzie read ()), ale nie implementuje interfejsu.

Outlaw Programmer
źródło
6

Moim zdaniem interfejsy powinny być preferowane zamiast niefunkcjonalnych klas abstrakcyjnych. Nie zdziwiłbym się, gdyby nastąpiłby tam hit wydajnościowy, ponieważ tworzy się tylko jeden obiekt zamiast analizować dwa i łączyć je (chociaż nie jestem pewien, nie znam wewnętrznego działania OOP PHP).

Prawdą jest, że interfejsy są mniej przydatne / znaczące niż w przypadku, powiedzmy, Java. Z drugiej strony PHP6 wprowadzi jeszcze więcej podpowiedzi typu, w tym podpowiedzi typu dla zwracanych wartości. To powinno zwiększyć wartość interfejsów PHP.

tl; dr: interfejsy definiuje listę metod, które należy stosować (think API), podczas gdy klasa abstrakcyjna zapewnia pewne podstawowe / wspólne funkcje, które podklasy dostosowują do konkretnych potrzeb.

Henrik Paul
źródło
PHP 6 nigdy nie zostanie wydany. PHP 6 był projektem rozwijanym w latach 2005-2010, ale został opóźniony i ostatecznie anulowany. PHP 7 to kolejna wersja, głównie w celu uniknięcia pomyłek z poprzednim projektem PHP 6.
Ashu Jha,
5

Nie pamiętam, czy PHP różni się pod tym względem, ale w Javie możesz zaimplementować wiele interfejsów, ale nie możesz odziedziczyć wielu klas abstrakcyjnych. Zakładam, że PHP działa w ten sam sposób.

W PHP możesz zastosować wiele interfejsów, oddzielając je przecinkami (myślę, że nie uważam tego za czyste rozwiązanie).

Jeśli chodzi o wiele klas abstrakcyjnych, możesz mieć wiele streszczeń rozciągających się nawzajem (znowu, nie jestem do końca tego pewien, ale myślę, że już gdzieś to widziałem). Jedyne, czego nie możesz przedłużyć, to klasa ostateczna.

Ross
źródło
4

Interfejsy nie zwiększą wydajności twojego kodu ani nic podobnego, ale mogą znacznie przyczynić się do jego utrzymania. Prawdą jest, że do ustanowienia interfejsu do kodu można użyć klasy abstrakcyjnej (lub nawet klasy nieabstrakcyjnej), ale odpowiednie interfejsy (zdefiniowane za pomocą słowa kluczowego i zawierające tylko sygnatury metod) są po prostu łatwiejsze do posortuj i przeczytaj.

Biorąc to pod uwagę, staram się używać dyskrecji przy podejmowaniu decyzji, czy użyć interfejsu nad klasą. Czasami chcę domyślnych implementacji metod lub zmiennych, które będą wspólne dla wszystkich podklas.

Oczywiście kwestia implementacji wielu interfejsów również jest rozsądna. Jeśli masz klasę, która implementuje wiele interfejsów, możesz użyć obiektu tej klasy jako różnych typów w tej samej aplikacji.

Fakt, że twoje pytanie dotyczy PHP, sprawia, że ​​jest to trochę bardziej interesujące. Pisanie na interfejsach wciąż nie jest niezwykle potrzebne w PHP, gdzie można dosłownie dowolnie nakarmić dowolną metodę, niezależnie od jej typu. Możesz statycznie wpisać parametry metody, ale niektóre z nich są zepsute (ciąg, jak sądzę, powoduje pewne czkawki). Połącz to z faktem, że nie możesz wpisać większości innych referencji, a próba wymuszenia pisania statycznego w PHP ( w tym momencie ) nie ma dużej wartości . Z tego powodu wartość interfejsów w PHP , w tym momenciejest o wiele mniej niż w silniej pisanych językach. Mają zaletę czytelności, ale niewiele więcej. Wielokrotne wdrożenie nie jest nawet korzystne, ponieważ nadal musisz zadeklarować metody i nadać im treści wewnątrz implementatora.

Brian Warshaw
źródło
2

Poniżej znajdują się punkty dotyczące interfejsu PHP

  1. Służy do zdefiniowania wymaganej liczby metod w klasie [jeśli chcesz załadować html, wówczas wymagany jest identyfikator i nazwa, więc w tym przypadku interfejs obejmuje setID i setName].
  2. Interfejs ściśle wymusza na klasie uwzględnienie wszystkich zdefiniowanych w nim metod.
  3. Metodę można zdefiniować tylko w interfejsie z publiczną dostępnością.
  4. Możesz także rozszerzyć interfejs jak klasa. Możesz rozszerzyć interfejs w php używając słowa kluczowego extends.
  5. Rozszerz wiele interfejsów.
  6. Nie można zaimplementować 2 interfejsów, jeśli oba współużytkują funkcję o tej samej nazwie. Wyrzuci błąd.

Przykładowy kod:

interface test{
    public function A($i);
    public function B($j = 20);
}

class xyz implements test{
    public function A($a){
        echo "CLASS A Value is ".$a;
    }
    public function B($b){
        echo "CLASS B Value is ".$b;
    }
}
$x = new xyz();
echo $x->A(11);
echo "<br/>";
echo $x->B(10);
vivek s vamja
źródło
2

Widzieliśmy, że abstrakcyjne klasy i interfejsy są podobne, ponieważ zapewniają abstrakcyjne metody, które muszą być zaimplementowane w klasach potomnych. Jednak nadal mają następujące różnice:

1. Interfejsy mogą zawierać metody abstrakcyjne i stałe, ale nie mogą zawierać konkretnych metod i zmiennych.

2. Wszystkie metody interfejsu muszą znajdować się w zakresie widoczności publicznej .

3. Klasa może implementować więcej niż jeden interfejs, podczas gdy może dziedziczyć tylko jedną klasę abstrakcyjną.

                                  interface                      abstract class
the code                     - abstract methods               - abstract methods
                             - constants                      - constants                  
                                                              - concrete methods
                                                              - concrete variables

access modifiers             
                             - public                         - public
                                                              - protected
                                                              - private
                                                                etc.
number of parents          The same class can implement
                           more than 1 interface              The child class can 
                                                              inherit only from 1 abstract class

Mam nadzieję, że pomoże to każdemu zrozumieć!

Zatrudnij Gohel
źródło
2

Interfejsy są jak twoje geny.

Zajęcia abstrakcyjne są jak twoi prawdziwi rodzice.

Ich cele są dziedziczne, ale w przypadku klas abstrakcyjnych a interfejsów dziedziczone są bardziej szczegółowe.

Tapha
źródło
2

Nie znam innych języków, jaka jest tam koncepcja interfejsu. Ale w przypadku PHP postaram się jak najlepiej to wyjaśnić. Po prostu bądź cierpliwy i proszę o komentarz, jeśli to pomogło.

Interfejs działa jako „kontrakty”, określając, co robi zestaw podklas, ale nie sposób, w jaki to robią.

Zasada

  1. Interfejs nie może być utworzony.

  2. Nie można zaimplementować żadnej metody w interfejsie, tzn. Zawiera ona tylko. Podpis tej metody, ale nie szczegóły (treść).

  3. Interfejsy mogą zawierać metody i / lub stałe, ale bez atrybutów. Stałe interfejsu mają takie same ograniczenia jak stałe klasy. Metody interfejsu są domyślnie abstrakcyjne.

  4. Interfejsy nie mogą deklarować konstruktorów ani destruktorów, ponieważ są to szczegóły implementacji na poziomie klasy.

  5. Wszystkie metody interfejsu muszą mieć widoczność publiczną.

A teraz weźmy przykład. Załóżmy, że mamy dwie zabawki: jedna to pies, a druga to kot.

Jak wiemy pies szczeka, a miauczenie kotów. Obaj mają tę samą metodę mówienia, ale mają inną funkcjonalność lub implementację. Załóżmy, że dajemy użytkownikowi pilot zdalnego sterowania z przyciskiem mówienia.

Gdy użytkownik naciśnie przycisk Mów, zabawka musi mówić, nie ma znaczenia, czy jest to Pies, czy Kot.

To dobry przypadek użycia interfejsu, a nie klasy abstrakcyjnej, ponieważ implementacje są różne. Czemu? Zapamiętaj

Jeśli potrzebujesz wesprzeć klasy potomne poprzez dodanie jakiejś nieabstrakcyjnej metody, powinieneś użyć klas abstrakcyjnych. W przeciwnym razie interfejsy byłyby twoim wyborem.

Społeczność
źródło