• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zrozumienie interfejsów

Object Storage Arubacloud
0 głosów
1,155 wizyt
pytanie zadane 25 lipca 2018 w PHP przez Luna Cognita Dyskutant (8,130 p.)
Witam,

Potrzebuję solidnego artykułu dotyczącego sensu implementacji interfejsów w PHP, takiego który wyczerpywałby inne. Na chwilę obecną nie znalazłem owego stąd prośba na tym forum.

Co do kwestii samych interfejsów zrozumiałem tylko, że jest on zbiorem nazw funkcji (metod) jak i właściwości (zmienne w klasie), oraz to, że można go wielokrotnie dziedziczyć, lecz nadal nie widzę głębszego sensu jego implementacji, dodam że dopiero próbuję stworzyć szablon własnego MVC.

Pozdrawiam :)
komentarz 25 lipca 2018 przez RafalS VIP (122,820 p.)
może być po angielsku?
komentarz 25 lipca 2018 przez Luna Cognita Dyskutant (8,130 p.)
tak

5 odpowiedzi

+1 głos
odpowiedź 25 lipca 2018 przez niezalogowany
Jest to zbiór metod i właściwości, które jakaś klasa będzie musiała implementować. Czyli określasz w interfejsie - CO musi zawierać w sobie pewna KLASA, która będzie implementować ten interfejs.

Ogólnie też się niedawno tego uczyłem, więc mogę niezrozumiale tłumaczyć, ale to co zrozumiałem opisałem :)

Ogólnie widzę duży sens w istnieniu czegoś takiego, bo możesz sobie gdzieś tam na początku kodu określić podstawowe interfejsy, a później w kodzie jak będziesz tworzył klasy to możesz wesprzeć się interfejsem, aby na pewno napisać klasę poprawnie - czyli zaimplementować wszystkie niezbędne metody i właściwości, które musi zawierać.
Przy dużej ilości kodu i dużemu skomplikowaniu interfejsy pewnie mają ogromny sens - bo nie musisz wszystkiego pamiętać, a w razie czego wyskoczy błąd i Cię poinformuje, że nie brakuje tego i tamtego
+1 głos
odpowiedź 25 lipca 2018 przez Assasz Nałogowiec (30,460 p.)

W PHP do wielokrotnego dziedziczenia służą traity, nie interfejsy. Interfejsy również nie mogą posiadać deklaracji własności (jedynie stałe), lecz można to "ominąć" stosując deklaracje getterów lub setterów. Zadaniem interfejsów jest przede wszystkim łączenie klas w większe moduły, gdzie każda klasa zachowuje się podobnie - implementuje te same metody, które mogą być inne, ale koniec końców będą robić to samo. Przykład:

interface FigureInterface
{
    // każda figura posiada pole powierzchni, które można w pewien sposób obliczyć
    public function calculateArea(): float;
}

class Rectangle implements FigureInterface
{
    private $a;

    private $b;

    public function calculateArea(): float
    {
        // oblicza pole powierzchni
        return $this->a * $this->b;
    }
}

class Square implements FigureInterface
{
    private $a;

    public function calculateArea(): float
    {
        // również oblicza pole powierzchni, ale w inny sposób
        return $this->a * $this->a;
    }
}

Stosownie interfejsów jest sposobem na implementację polimorfizmu. Dzięki temu instancje różnych klas będą się zachowywać podobnie, albo i identycznie, co można wykorzystać np. przy Dependency Injection lub też Dependency Inversion. Powiedzmy, że chcesz teraz zrobić klasę - kolekcję przechowującą różne figury:

class FigureCollection
{
    private $figures = [];

    public function add(FigureInterface $figure): void
    {
        // dzięki zastosowaniu interfejsu możesz dodać zarówno kwadrat jak i prostokąt, 
        // ale nie dodasz już np. worka kartofli, który figurą nie jest
    
        $this->figures[] = $figure;
    }
}

Teraz dodajmy metodę obliczającą łączne pole powierzchni figur:

class FigureCollection
{
    private $figures = [];

    public function calculateTotalArea(): float
    {
        // ponieważ $figures zawiera jedynie obiekty implementujące nasz interfejs 
        // możemy obliczyć łączne pole powierzchni tych figur używając metodę calculateArea()
        
        $area = 0;
        
        foreach ($this->figures as $figure) {
            $area += $figure->calculateArea();
        }

        return $area;
    }
}

To tylko jeden z prostszych, akademickich przykładów zastosowania interfejsów. Im bardziej będziesz się zagłębiać w OOP oraz wzorce architektoniczne, tym bardziej będziesz doceniać interfejsy.

+1 głos
odpowiedź 26 lipca 2018 przez Mariusz08 Maniak (62,300 p.)

Koledzy wyżej powiedzieli już chyba wystarczająco dużo nt. samej idei interfejsów, więc ja dodam tylko jeden przykład:

Robisz forum/sklep internetowy/bloga (cokolwiek) i chcesz, aby użytkownicy mogli dodawać własne wtyczki do Twojego systemu.  Niby fajnie, bo nie będzie nikt edytował kodu bloga, będzie łatwiej pomóc, a także powstanie małe community które będzie tworzyło pluginy które każdy może zaimplementować u siebie. Ale - od strony programistycznej każdy plugin musi zawierać pewne elementy

  • metodę init() dla ustawiania opcji systemu, konfiguracji, ładowania informacji o wtyczce,
  • metodę enable() dla włączenia wtyczki z panelu administratora,
  • metodę disable() dla wyłączenia wtyczki z panelu administratora, 
  • metodę log() dla zapisywania logów wtyczki do pliku tekstowego.

Ale jak zmusić użytkownika, aby jego plugin zawierał te elementy? Tutaj z pomocą przychodzą nam interfejsy. Możesz nakazać, aby każdy plugin implementował interfejs PluginInterface. Jego zawartość

interface PluginInterface
{
    public function init();
    public function enable();
    public function disable();
    public function log();
}

I każdy plugin musi implementować ten interfejs. Jeśli go nie zaimplementuje, wtyczka nie będzie dostępna w panelu administratora. Jeśli zaś zaimplementuje, to mamy pewność, że te wszystkie metody są zaimplementowane (inaczej PHP wyświetli błąd) i możemy wywoływać te funkcję bez obaw, że wystąpi jakiś problem. Proste? Proste.

komentarz 26 lipca 2018 przez Luna Cognita Dyskutant (8,130 p.)
Czyli w skrócie interfejs to zbiór metod jak i właściwości, jakie obojętnie jaka klasa implementująca go musi posiadać funkcje z takimi nazwami? A co jeśli jedna klasa posiada metodę init(); implementując interfejs, natomiast druga również posiada metodę init(); implementując interfejs lecz w tej drugiej działanie funkcji znacząco się różni od tej w klasie pierwszej? Chodzi tutaj tylko o nazewnictwo?
komentarz 26 lipca 2018 przez Mariusz08 Maniak (62,300 p.)

Czyli w skrócie interfejs to zbiór metod jak i właściwości

Interfejs nie implementuje właściwości. Można w nim używać tylko metod. (można implementować stałe)

 jakie obojętnie jaka klasa implementująca go musi posiadać funkcje z takimi nazwami?

Dokładnie tak

A co jeśli jedna klasa posiada metodę init(); implementując interfejs, natomiast druga również posiada metodę init();

 Um... Jedna klasa implementuje interfejs jest ok. Druga też implementuje interfejs i też jest ok. (chyba, że chodzi o przypadek, kiedy przed implementacją klasa posiada metodę init(), wtedy to ta metoda zostaje tak jak jest, tak jak mówisz chodzi tylko o kwestię nazewnictwa)

 

0 głosów
odpowiedź 25 lipca 2018 przez Aisekai Nałogowiec (42,190 p.)
Nie wiem jaka jest różnica między interfejsami w PHP, ale mniej więcej mogę Ci powiedzieć czym są interfejsy w javie. Najpierw formalna definicja:

-Interfejs to zestaw metod które musi zaimplementować klasa implementująca interfejs. O zmiennych nie będę mówił, bo w javie istnieje możliwość deklarowania zmiennych w interfejsie ale zostaną i tak one zadeklarowane jako final.

Interfejsy pełnią ważną rolę w szeroko pojętej abstrakcji i w programowaniu obiektowym, wykorzystując polimorfizm. Przykład ze zwierzętami i komendą "daj_głos" gdy klasy takie jak Pies, Kot czy Papuga implementują interfejs posiadający tą metodę.

Weźmy bardziej praktyczny przykład, czyli Listy w javie - dynamiczne struktury danych. Jak każda z dynamicznych struktur danych, ma możliwość dodawania elementów do list. I tutaj mamy kilka możliwości: może to być na zasadzie tablic (jak np http://www.vogella.com/tutorials/JavaDatastructureList/article.html ) albo na zasadzie listy, gdzie i-ty element ma jako pole referencję do i+1 elementu. I tutaj pojawiają nam się zarówno plusy jak i minusy każdej z implementacji.

I tutaj pojawia nam się idea interfejsu. Lepiej stworzyć zestaw metod (dodawanie, usuwanie, pobieranie elementu itd) i zaimplementować te metody w dwóch klasach i jako typ zmiennej podawać nazwę interfejsu (tutaj List) a tworząc obiekty podawać jego implementacje (ArrayList i LinkedList). W chwili, gdy będziesz coś chciał zmienić implementacje metod, będzie się to sprowadzało do zmiany obiektu implementującego dany interfejs, jedna linijka kodu zamiast szukać w kilku miejscach gdzie masz coś zmienić.

Innym przykładem może być baza danych. Istnieją takie bazy danych jak MySQL, h2, mongoDB etc. jedna może być lepsza od drugiej w niektórych sytuacjach, jeżeli zostanie podjęta decyzja o zmianie bazy danych - nie trzeba zmieniać reszty kodu, wystarczy zmienić implementację interfejsu.

PS: Tak jak mówiłem, nie jest to PHP jednak w OOP według mnie dużej róznicy między interfejsami w PHP czy Javie nie powinno być (może się różnić tym, że np w Javie nie ma możliwości dziedziczenia wielokrotnego, a w innym języku może być więc implementowanie interfejsów może zastąpić dziedziczenie wielokrotne)
0 głosów
odpowiedź 25 lipca 2018 przez CenterPL Pasjonat (19,070 p.)

Wytłumaczę sens na prostym przykładzie - masz coś takiego jak SomeRepositoryInterface a w nim metody typu getSomethingById, getSomethingList, countSomething. Jest to interfejs repozytorium, który pobiera dane z bazy.

Teraz masz 3 rodzaje baz danych - MySQL, Mongo i SQLite. No i skoro 3 rodzaje baz, to dane pobierasz na 3 różne rodzaje:

MySQLSomeRepository, MongoSomeRepository, SQLiteSomeRepository i wszystkie 3 implementują interfejs SomeRepositoryInterfejs, ale każda z tych 3 klas ma inne implementacje tych samych metod. Dzięki temu w DI możesz podstawiać co chcesz bo będą to instacje SomeRepositoryInterface. Czyli robisz coś takiego np.:

__construct(SomeRepositoryInterface $repository)
{
    $this->repository = $repository;
}

dzięki czemu nie interesuję Cię konkretna implementacja, ważne, że $repository ma metody count, getById itp. A jak to działa to już sprawa konkretnej klasy, Ciebie to nie interere.

Podobne pytania

+1 głos
1 odpowiedź 4,140 wizyt
pytanie zadane 23 października 2015 w C# przez Wiktor Stary wyjadacz (11,120 p.)
0 głosów
1 odpowiedź 159 wizyt
pytanie zadane 9 września 2020 w Java przez Jonasz Nowicjusz (230 p.)
0 głosów
1 odpowiedź 142 wizyt
pytanie zadane 14 września 2020 w PHP przez Assasz Nałogowiec (30,460 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...