Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Strict Standards
Forum PHP.pl > Forum > PHP
likemandrake
Witam

Mam taki mini problem, mam o to taki zestaw klas:

  1. <?php
  2. class A {
  3.   // Zestaw metod
  4. }
  5.  
  6. class B extends A {
  7.   // Dodatkowy zestaw metod
  8. }
  9.  
  10. abstract class C {
  11.   public function setObject(A $object) {
  12.      
  13.   }
  14. }
  15.  
  16. abstract class D extends class C {
  17.   public function setObject(B $object) {
  18.      
  19.   }
  20. }
  21.  
  22. class Concrete extends class D {
  23.  
  24. }
  25. ?>


Gdy działam na obiekcie klasy Concrete, php wywala mi taki komunikat:
Cytat
Strict Standards: Declaration of D::setObject() should be compatible with that of C::setObject() in [...]


Co o tym myślicie, czy nie jest to troszkę na wyrost? Wiadomo, co chciałem przez to osiągnąć... Jak do tego podejść tak w ogóle?

Pozdrawiam
ayeo
Nie rozumiem pytania. Co jest na wyrost? Od tego są klasy abstrakcyjne, żeby je potem rozszerzać w klasach potomnych. I tyle. Jak deklarujesz metodę w funkcji abstrakcyjnej to klasa dziedzicząca musi implementować tą metodę. Tak to działa.

Pozdrawiam!
230005
Zdaje się, że obie metody setObject() powinny przyjmować jako argument ten sam typ, a u ciebie to A i B :]
likemandrake
Dokładnie wiem jak to działa smile.gif Proszę zwrócić uwagę na deklarację metody setObject klasy C i D i zaznaczam, że nie są to metody abstrakcyjne. Rozumiem, jakby metoda setObject w klasie C została zadeklarowana jako abstrakcyjna, to PHP mógłby rzeczywiście u mnie wymagać 100% kompatybilności, a tak to są zwykłe metody, tyle że w klasach abstrakcyjnych.

Cytat(230005 @ 3.02.2009, 20:38:42 ) *
Zdaje się, że obie metody setObject() powinny przyjmować jako argument ten sam typ, a u ciebie to A i B :]


No właśnie, PHP mi nakazuje aby te metody były ze sobą kompatybilne, mimo tego, że nie są to metody abstrakcyjne. Stąd moje pytanie, jak do tego podejść.

Po za tym jak widać klasa B dziedziczy po klasie A....
ayeo
Witam!

Faktycznie moje niedopatrzenie. Wygląda to na błąd PHP w sumie. Dziwna sprawa smile.gif

Pozdrawiam!
likemandrake
Ściągnąłem ograniczenie abstract z klasy C i D i komunikat pojawia się nadal. Dopiero, gdy w metodzie D::setObject() zmienię przyjmowany parametr na A, PHP nie warczy, a tego nie mogę tak zrobić.

Wniosek z tego taki, że PHP w wersji 5.2.6 ma taki specyficzny błąd.

Czy mógłby ktoś przetestować taki zestaw klas w PHP 5.2.8?
Zaznaczam, że przed wczytaniem pliku z zestawem klas z powyższego kodu musimy ustawić raportowanie błędów na 'E_ALL | E_STRICT'.
dr_bonzo
Cytat
No właśnie, PHP mi nakazuje aby te metody były ze sobą kompatybilne, mimo tego, że nie są to metody abstrakcyjne. Stąd moje pytanie, jak do tego podejść.

W php nie ma przeciazania metod (ta sama nazwa a inne parametry) - wiec nadpisujesz metode w podklasie (zmieniasz jej implementacje), a wiec musza miec te same paramery.

Skoro ja nadpisujesz to musisz zachowac jej sygnature - typ parametru (skoro go specyfikujesz), czemu?
Z definicji OOP:
  1. <?php
  2. $c = new Concrete_C(); // extends C
  3. $c->setObject( new A() ); // OK
  4. ?>


Tworzysz sobie obiekt typu C (czyli klasy C lub pochodnych == klasy C, D, Concrete, whatever).
Zgodnie z polimorfizmem mozesz wymienic obiekt na inna podklase klasy C, i powinienes miec mozliwosc wykonywania na nim tych samych operacji,
tu: przekazania obiektu klasy A do metody setObject(), ale

  1. <?php
  2. $c = new Concrete_D(); // extends D
  3. $c->setObject( new A() ); // !!! NIE ZADZIALA, bo A nie jest B (dziedziczenie to relacja odwrotna, B jest A)
  4. ?>



Wiem ze PHP to nie Java/C# i ze jest dynamicznym jezykiem, ale po co w takim razie korzystasz z type-hintingu skoro nie chcesz sie do jego zasad dostosowac?

  1. <?php
  2. // phph 5.2.6
  3. error_reporting( E_ALL | E_STRICT );
  4.  
  5. class A {
  6.    var $x = 3;
  7.  // Zestaw metod
  8.  protected $object = null;
  9. }
  10.  
  11. class B extends A {
  12.  // Dodatkowy zestaw metod
  13. }
  14.  
  15. abstract class C {
  16.  public function setObject(A $object) {
  17.     $this->object = $object;
  18.  }
  19. }
  20.  
  21. abstract class D extends C {
  22.  public function setObject(B $object) {
  23.     $this->object = $object;    
  24.  }
  25. }
  26.  
  27. class Concrete extends D {
  28.  
  29. }
  30. class Concrete_D extends  D {
  31.  
  32. }
  33. class Concrete_C extends C {
  34.  
  35. }
  36.  
  37. $c = new Concrete_C();
  38. $c->setObject( new A() );
  39.  
  40. print_r( $c );
  41.  
  42. $c = new Concrete_D();
  43. $c->setObject( new B() );  // przyjmuje tylko B
  44. $c->setObject( new A() );  // z A nie zadziala
  45.  
  46. print_r( $c );
  47. ?>



// pomógł++
// ayeo
likemandrake
Programowałem w C++ i rzeczywiście jeśliby klasy które napisałem powyżej przestawić na ten język, klasa D zawierałaby dwie wersje metod (taką która przyjmuje obiekty klasy A, oraz taką która przyjmuje obiekty klasy B ).

To by wszystko wyjaśniało, dlaczego tak się dzieje w PHP, możnaby sobie powiedzieć, że z powodu braku funkcji przeładowywania metod, programiści mogliby rozwiązać ten problem inaczej smile.gif

Cóż najlepszym w takim wypadku będzie w metodzie klasy D przyjmować parametr typu A, oraz rzucać wyjątek w metodzie, jeśli nie przekazano obiektu klasy B.

Pozdrawiam
Crozin
A czy przypadkiem klasy A i B nie mogłby implementować jakiegoś interfaceu, a metoda setObject mieć sygnaturę public setObject(myInterface)? Chyba, że te dwa obiekty mają robić coś zupełnie innego, ale wtedy możnaby zacząć się zastanawiać czy aby napewno to co robisz jest poprawne?
likemandrake
Tak, mam interfejs, po którym dziedziczy podana wyżej klasa C.

Klasa A, jest to klasa z pakietu Zend Framework, klasa B jest moją klasą, która rozszerza o pare dodatkowych funkcji klasę A.

Znów klasa D dziedziczy po klasie C, ale w porównaniu do klasy C, klasa D korzysta z dodatkowych funkcji nadanych w klasie B.

Efekt jest taki, że klasa, która tu w ogóle nie jest opisana, wymagająca w/w interfejsu, dostaje to co chce i w taki sposób jak powinna. Dane na których wspomniana nieopisana klasa operuje są przygotowane w lepszy sposób przy użyciu zestawu D i B, niż gwarantowałby mi to zestaw C i A.

Pozdrawiam
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.