Czy klasa może rozszerzyć klasę i zaimplementować interfejs

100

Czy klasa może rozszerzyć zarówno interfejs, jak i inną klasę w PHP?
Zasadniczo chcę to zrobić:

interface databaseInterface{
 public function query($q);
 public function escape($s);
 //more methods
}

class database{ //extends both mysqli and implements databaseInterface
 //etc.
}

Jak można to zrobić, po prostu robiąc:

class database implements databaseInterface extends mysqli{ 

powoduje błąd krytyczny:

Błąd analizy: błąd składni, nieoczekiwany T_EXTENDS, oczekiwanie „{” w * pliku * w wierszu * w wierszu *
Pim Jager
źródło
18
Jak to jest zbyt zlokalizowane ?! „To pytanie raczej nie pomoże przyszłym gościom”. Jednak najlepsza odpowiedź ma 33 głosy za, a pytanie 4 gwiazdki!
duality_

Odpowiedzi:

177

Spróbuj na odwrót:

class database extends mysqli implements databaseInterface { ...}

To powinno działać.

Simon Lehmann
źródło
Ach, bardzo dziękuję. Dlaczego właściwie jest tak, że mają być na odwrót?
Pim Jager
14
Ponieważ możesz dziedziczyć tylko jedną klasę i możesz zaimplementować dowolną liczbę interfejsów, prawdopodobnie była to kwestia cukru składniowego. Pamiętaj też, że jeśli Twoja podklasa implementuje jakiekolwiek interfejsy, pojawi się to również na liście zaimplementowanych metod. Więc umieszczenie ich w takiej kolejności ma pewien sens.
Drew
Czy to zła praktyka?
Mohammed Shamshid
21

Tak, może. Wystarczy zachować odpowiednią kolejność.

class database extends mysqli implements databaseInterface { ... }

Ponadto klasa może implementować więcej niż jeden interfejs. Po prostu oddziel je przecinkami.

Czuję się jednak zobowiązany do ostrzeżenia, że rozszerzenie klasy mysqli to niesamowicie zły pomysł . Dziedziczenie samo w sobie jest prawdopodobnie najbardziej przereklamowaną i nadużywaną koncepcją w programowaniu obiektowym.

Zamiast tego radziłbym robić rzeczy związane z db metodą mysqli (lub sposobem PDO).

Poza tym drobiazg, ale konwencje nazewnictwa mają znaczenie. Twoja klasa databasewydaje się wtedy bardziej ogólna mysqli, dlatego sugeruje, że ta ostatnia dziedziczy po, databasea nie odwrotnie.

Michał Rudnicki
źródło
1
Dlaczego rozszerzenie klasy mysqli to zły pomysł?
Pim Jager
11
Po pierwsze, ponieważ to nie jest twoje. Kiedy faceci mysqli zdecydują się coś zmienić, zachowanie podklasy również się zmieni. Po drugie, dziedziczenie służy do SPECJALIZACJI, a nie ROZSZERZANIA o dodatkowe funkcje. To jest najbardziej niezrozumiana rzecz w OOP. Zasadniczo staram się rozszerzać tylko klasy abstrakcyjne.
Michał Rudnicki
Michał - czym zmiana w mysqli byłaby inna dla programisty stosującego podejście polimorficzne od zagregowanego / skomponowanego? Nadal będziesz musiał zaktualizować kod, aby obsłużyć zmiany.
Peter Bailey
2
Znam wzór adaptera. Mówię tylko, że jeśli nazwa metody ulegnie zmianie lub stanie się przestarzała, nadal będziesz musiał zmienić kod w obu scenariuszach. Chociaż zgadzam się, że podejście niepolimorficzne jest lepsze w tym scenariuszu, nie wierzę, że adapter byłby „odporny” na zmiany.
Peter Bailey
2
Będziesz musiał zmienić tylko kod adaptera, a nie wszystkie miejsca używające tego kodu. Dzięki kompozycji możesz zapewnić warstwę kompatybilności bez względu na wszystko, podczas gdy dzięki dziedziczeniu możesz w najlepszym razie nazwać to hackiem. I, skorygowałem, adapter zapewniłby lepszą odporność na zmiany.
Michał Rudnicki
6

tak, w rzeczywistości, jeśli chcesz zaimplementować wiele interfejsów, możesz zrobić to w następujący sposób:

public class MyClass extends BaseClass implements myInterface1, myInterface2, myInterface3{ 

}
nullpointer
źródło