Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Interferfejs, wielodziedziczenie
Forum PHP.pl > Forum > PHP > Object-oriented programming
naitsabes
Czesc, jakis czas temu przeczytałem, że jedyna opcja dla wielodziedziczenia jest Implementowanie interfejsu...


Poczytałem, ok stworzyłem niby interfejs, ale nie mam pojecia jak to wszystko działa.

Wydaje mi sie ze to działa w ten sposob

interfejs
{
funkcja()
}

clasa dajaca do interfejsu
{
funkcja()
{}
}


i pozniej mozna pobrac z interfejsu ta funkcje. Wydawało mi sie, że dobrze zrozumiałem to ale niestety nie moge stworzyc zadnego kodu, byc moze zle pojąłem sposob działania interfejsu.


Bylbym wdzieczny gdyby ktos zrobil jakis prosty przyklad, samo echo i zmienne, jak zrobic oraz wykorzystac interfejs.
Duzy czytalem, napisanie tutaj to ostatecznosc.


Dziekuje za cierpliwosc i przepraszam za prostote pytania


Pozdrawiam
destroyerr
Czy tutaj masz zbyt mało przykładów?
Hoku
  1. interface A { function a(); }
  2. interface B { function b(); }
  3.  
  4. class C implements A, B {
  5. function a() { echo "a\n"; }
  6. function b() { echo "b\n"; }
  7. }


interfejsy zawierają jedynie deklaracje funkcji, definicje funkcji są w klasach.

interfejsy zawierają jedynie informacje co dana klasa implementująca interfejs musi zawierać w sobie

przykład klasa samochód implementuje interfejs silnika, karoserii itp. musi je zawierać nie ma auta bez nich smile.gif

wielodziedziczenie to zło istniejące w C++, jest dość problematyczne, gdyż wprowadza spory bałagan problematykę istnienia metod o tych samych nazwach w klasach z których dziedziczymy itp.
Świadczy też o złej architekturze.

Dziedziczyć można jedynie po klasach interfejsy się implementuje
el.pablo.72
Sensowne i proste rozwiązanie oferuje Framework CodeIgniter, jest oparte na plikach.
destroyerr
@el.pablo.72 nie wprowadzaj zamieszania. Framework nie ma nic wspólnego z interfejsami i wielodziediczeniem, a już na pewno nie mają na to wpływu pliki.
sarxos
Ale framework to chociaż porządkuje. W PHP brak jest eleganckiego rozwiązania, które umożliwiłoby includowanie pakietów i klas (np. tak jak jest to w Javie). Jakikolwiek mechanizm, który doprowadza to do porządku jest wysoce użyteczny :)
drPayton
A co ma piernik do wiatraka? Autor nie chce gotowca, którego będzie używał bez zrozumienia, chce pojąć temat. Proste i skuteczne wyjaśnienie podał @Hoku. Po co ten spam?


Ale skoro już, to się przyczepię:

Cytat(sarxos @ 15.06.2011, 15:14:05 ) *
(...) W PHP brak jest eleganckiego rozwiązania, które umożliwiłoby includowanie pakietów i klas (...)

Oczywiście, że jest. Czy eleganckie? Kwestia gustu, mi się podoba. Poznaj "magię" php, potem formuuj opinie wink.gif
Speedy
Implementowanie interfejsu i wielodziedziczenie, to dwie osobne sprawy. W PHP możesz implementować interfejsy, ale nie możesz korzystać z wielodziedziczenia. Jeśli chcesz mieć dostęp do funkcjonalności kilku klas w innej klasie możesz stworzyć obiekty tych klas w nowej klasie.
Np. Mamy 3 klasy: klasa1, klasa2 oraz klasa3 i chcemy użyć funkcjonalności z klas: klasa1 i klasa2 w klasie: klasa3. Możemy zrobić tak:

  1. <?php
  2. class klasa1 {
  3. public function funkcja1() {
  4. echo "funkcja1\n<br/>";
  5. }
  6. }
  7.  
  8. class klasa2 {
  9. public function funkcja2() {
  10. echo "funkcja2\n<br/>";
  11. }
  12. }
  13.  
  14. class klasa3 {
  15.  
  16. public $klasa1;
  17. public $klasa2;
  18.  
  19. public function __construct() {
  20. $this->klasa1 = new klasa1;
  21. $this->klasa2 = new klasa2;
  22. }
  23.  
  24. public fuction funkcja3() {
  25. $this->klasa1->funkcja1();
  26. $this->klasa2->funkcja2();
  27. }
  28.  
  29. }
  30.  
  31. $obiekt = new klasa3();
  32. $obiekt->funkcja3();
  33. ?>


Zamiast wielodziedziczenia, którego w PHP nie ma i które jest trochę sprzeczne z logiką programowania (choć w C++ jest) lub zamiast powyższego rozwiązania, możesz też użyć hierarchicznego uporządkowania klas np.

  1. <?php
  2. class klasa1 {
  3. public function funkcja1() {
  4. echo "funkcja1\n<br/>";
  5. }
  6. }
  7.  
  8. class klasa2 extends klasa1 {
  9. public function funkcja2() {
  10. echo "funkcja2\n<br/>";
  11. }
  12. }
  13.  
  14. class klasa3 extends klasa2 {
  15.  
  16. public function __construct() {
  17. }
  18.  
  19. public fuction funkcja3() {
  20. $this->funkcja1();
  21. $this->funkcja2();
  22. }
  23.  
  24. }
  25.  
  26. $obiekt = new klasa3();
  27. $obiekt->funkcja3();
  28. ?>


Przy tym rozwiązaniu trzeba pamiętać o tym, żeby klasy były logicznie uporządkowane. Nie zawsze jest sens stosować tego typu rozwiązanie.
darko
~Speedy nie do końca to takie dwie różne sprawy. Implementowanie kilku interfejsów zmusza programistę do zaimplementowania wszystkich metod zdefiniowanych w interfejsach, więc jest to nieco zbliżone do "wielodziedziczenia" poprzez wymuszenie implementacji. Oczywiście w php nigdy nie było możliwości dziedziczenia po kilku klasach i prawdopodobnie nigdy nie będzie takiej funkcjonalności, ale interfejsy pozwalają przybliżyć się nieco do tego mechanizmu.
Fifi209
Cytat(sarxos @ 15.06.2011, 15:14:05 ) *
W PHP brak jest eleganckiego rozwiązania, które umożliwiłoby includowanie pakietów i klas (np. tak jak jest to w Javie).

A phar?
Cytat(sarxos @ 15.06.2011, 15:14:05 ) *
Jakikolwiek mechanizm, który doprowadza to do porządku jest wysoce użyteczny smile.gif

namespace + phar
Speedy
Cytat(darko @ 15.06.2011, 17:38:04 ) *
~Speedy nie do końca to takie dwie różne sprawy. Implementowanie kilku interfejsów zmusza programistę do zaimplementowania wszystkich metod zdefiniowanych w interfejsach, więc jest to nieco zbliżone do "wielodziedziczenia" poprzez wymuszenie implementacji. Oczywiście w php nigdy nie było możliwości dziedziczenia po kilku klasach i prawdopodobnie nigdy nie będzie takiej funkcjonalności, ale interfejsy pozwalają przybliżyć się nieco do tego mechanizmu.


W zasadzie tak, choć mamy wtedy do czynienia tylko z prototypami funkcji, a nie samymi funkcjami. Interfejsy tylko narzucają deklarację konkretnych funkcji. Implementacja, to nie jest to samo, co dziedziczenie.
cepa
wielodziedziczenie mozna zrobic wykorzystujac poprostu __call i refleksje, uzycie w praktyce bylo by np takie:

$a = new A();
$a->extend(new B());
$a->extend(new C());
$a->metodaZKlasyB();
$a->metodaZKlasyC();
Crozin
@cepa: Bardzo ładny przykład jednego z najgorszych możliwych kodów jaki może powstać.

Interfejsy nie są substytutem dla wielokrotnego dziedziczenia. Ogólnie nie powinieneś w ogóle chcieć korzystać z takiego rodzaju dziedziczenia. A gdy wydaje Ci się, że takie dziedziczenie ułatwiłoby Ci pracę oznacza to, iż najprawdopodobniej masz błąd w projekcie.
cepa
Cytat(Crozin @ 16.06.2011, 16:07:49 ) *
@cepa: Bardzo ładny przykład jednego z najgorszych możliwych kodów jaki może powstać.

@Crozin: Dales bardzo ladny przyklad swojej nieznajomosci wzorcow projektowych smile.gif

to co pokazalem wyzej to nic innego jak Dekorator, a stosowane w dokladnie tej formie co wyzej jest np: w Doctrine - behaviours, i jest naprawde bardzo przydatne smile.gif

problem z wielodziedziczeniem wynikal stad ze bylo naduzywane w C++, wymagalo rzutowania, i rodzilo wiele problemow np: http://en.wikipedia.org/wiki/Diamond_problem

Fifi209
Cytat(cepa @ 16.06.2011, 16:44:01 ) *
@Crozin: Dales bardzo ladny przyklad swojej nieznajomosci wzorcow projektowych smile.gif

Chciałbym w tym miejscu sprostować, to że pokazałeś wzorzec i coś takiego jest wzorcem, nie znaczy od razu że jest poprawny pod względem logiki i przejrzystości kodu, tak samo jak odradza się używania singletonów.
cepa
Cytat(Fifi209 @ 16.06.2011, 16:50:14 ) *
Chciałbym w tym miejscu sprostować, to że pokazałeś wzorzec i coś takiego jest wzorcem, nie znaczy od razu że jest poprawny pod względem logiki i przejrzystości kodu, tak samo jak odradza się używania singletonów.

dekorator to bezpieczna alternatywa dla wielokrotnego dziedziczenia bo nie rodzi problemow jak diament ktory wkleilem wyzej, tj: w jezyku kompilowanym dekorator eliminuje problem nakladania sie symboli metod na siebie, w php magiczne __call mozna prosto wykorzystac jako proxy dla dekoratorow, taki mechanizm umozliwia np: rozszerzanie api obiektu, idac dalej tym tropem dochodzimy do meta programowania gdzie nie tylko obiekt sie liczy ale to "z czego jest zbudowany"

singleton i inne wzorce to tylko narzedzia, nie ma zlych lub dobrych wzorcow, sa sytuacje ze nawet tak znienawidzone goto jest najlepszym rozwiazaniem
Crozin
Cytat
@Crozin: Dales bardzo ladny przyklad swojej nieznajomosci wzorcow projektowych smile.gif

to co pokazalem wyzej to nic innego jak Dekorator, a stosowane w dokladnie tej formie co wyzej jest np: w Doctrine - behaviours, i jest naprawde bardzo przydatne smile.gif
Problem w tym, że dekorator zakłada rozwijanie istniejącego obiektu, a nie dodawanie do niego kompletnie nowej, z niczym nie związanej funkcjonalności. Już o jednoczesnej obsłudze wielu różnorakich obiektów nie wspominając. Znajomość wzorców to nie tylko wyuczenie się jakie konstrukcje wyglądają jak jakiś tam wzorzec.

Cytat
problem z wielodziedziczeniem wynikal stad ze bylo naduzywane w C++, wymagalo rzutowania, i rodzilo wiele problemow np: http://en.wikipedia.org/wiki/Diamond_problem
Nawet nie to. Problemem jest to, że wielokrotne dziedziczenie jest z reguły kompletnie zbędne, ale co ważniejsze to narzędzie pozwala na zbyt wiele nadużyć. Pierwszy lepszy przykład, wikipedia:
Kod
Human
Worker         :  Human
Musician       :  Human, Worker
StreetMusician :  Human, Musician, Worker
Ktoś uznał, że muzyk (zawód, profesja) to wyspecjalizowana forma człowieka (zwierzęcia).
cepa
Cytat(Crozin @ 16.06.2011, 19:08:57 ) *
Problem w tym, że dekorator zakłada rozwijanie istniejącego obiektu, a nie dodawanie do niego kompletnie nowej, z niczym nie związanej funkcjonalności. Już o jednoczesnej obsłudze wielu różnorakich obiektów nie wspominając. Znajomość wzorców to nie tylko wyuczenie się jakie konstrukcje wyglądają jak jakiś tam wzorzec.


ale to co napisalem wyzej to dokladnie rozwijanie istniejacego obiektu, najpierw tworze instancje pozniej dodaje do niej dekoratory
LSM
@Crozin : Czy nie uważasz że nadużycia wielodziedziczenia są po prostu winą niedoświadczonego programisty niż winą samego języka ? Pozwól, że zacytuję swojego mentora: (Chryste ratuj jeśli wywołam kolejną wojnę hehehe smile.gif )

Odn. wielodziedziczenia niech tylko zacytuję pewnego człowieka który o dziedziczeniu napisał w pewnym tomie klikadziesiąt stron:
"Często pojawia się sytuacja wymagająca połączenia ze sobą kilku abstrakcji: na przykład klasa może modelować 'pracownika' któego można traktować zarówno jako "osobę" , jak i jako "koszt" prowadzenia działalności jaki można odliczyć od podatku. Właśnie tu z pomocą przychodzi dziedziczenie wielokrotne [...]"
"Taka możliwość nazywana dziedziczeniem wielokrotnym, jest niezbędna do tworzenia odpornych obiektowych architektur poprzez łączenie ze sobą różnych abstrakcji [...]"
"Na początek musisz zrozumieć kiedy dziedziczenie wielokrotne jest przydatne. Przyjrzyjmy się zatem [...] . Taki przegląd jest bardzo potrzebny i to bynajmniej nie dlatego, żebyś docenił elegancję i prostotę dziedziczenia wielokrotnego czy też konieczność jego stosowania. Te kwestie są oczywiste dla każdego, kto miał czas i ochotę, przyjrzeć się bliżej zagadnieniu [...]"

"Ważniejsze jest to żeby obalić powszechny pogląd (rozpowszechniany głównie przez osoby posługujące się językami, które nie obsługują takiej postaci dziedziczenia), że dziedziczenie wielokrotne jest trudne, tajemnicze, podatne na błędy i przypomina obiektową wersję polecenia 'goto'.[...]"

"Zobaczysz, że wcale nie będziemy mieli problemów ze znalezieniem wartościowych przykładów . Problemem będzie raczej zatrzymanie powodzi dobrych pomysłów, która pojawi się, gdy tylko naruszymy tamę".

Źródło: Bertrand Meyer "programowanie zorientowane obiektowo"

Autor podaje na początek złe przykłady:
Nauczyciel extends Asystent
Student extends Asystent
OsobaZwiazanaZuniwersytetem extends Nauczyciel, Student

Potem podaje dobry (e):
Okna są jednocześnie drzewami, elementami list i prostokątami.
Samolot może być również środkiem trwałym.
Złożone figury.
(Rozważań na temat NUMERIC i COMPARABLE nie opisuje nie chce mi się cytować kurka całej książki ) :-)

Moim zdaniem wielodziedziczenie jest przydatne dla większych i skomplikowanych systemów (nie tam CMS, CRM, sklep internetowy, kolejny framework oneeyedsmiley02.png ) . Należy umieć wykorzystać co jezyk daje nam do dyspozycji - osobiście parę razy zdarzyło mi się ubolewać nad faktem że PHP nie ma wielodziedziczenia :-) , z prostej przyczyny: wielodziedziczenie sprawiłoby, że projekt byłby bardziej przejrzysty i logiczny, zamiast ratować się innego rodzaju rozwiązaniem.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.