Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."

[es] :: PHP :: Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."

[ Pregleda: 1783 | Odgovora: 4 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Goran Rakić
Beograd

Moderator
Član broj: 999
Poruke: 3766

Sajt: blog.goranrakic.com


+125 Profil

icon Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."01.10.2010. u 02:57 - pre 165 meseci
Imam mali problem koji ću ilustrovati primerom koda:

Code (php):
class Delegate {}
class CustomDelegate extends Delegate {}

interface Listener {
  public function add(Delegate $d);
}

/**
 * Prihvata samo CustomDelegate
 */

class CustomDelegateListener implements Listener {
  public function add(CustomDelegate $d) {}
}


Dakle imamo klasu Delegate i CustomDelegate koji je nasleđuje. Postoji Listener interfejs sa metodom koja prima Delegate. Međutim naš CustomDelegateListener koji implementira ovaj interfejs ne želi da primi bilo koji Delegate već baš CustomDelegate, tj. da postavi ovaj strožiji typehint. Ovaj kod daje: PHP Fatal error: Declaration of CustomDelegateListener::add() must be compatible with that of Listener::add()

Probao sam da izbacim typehint iz interfejsa, ali ni to ne pomaže. PHP traži da izbacim typehint i iz interfejsa i iz CustomDelegateListener klase. Probao sam da definišem izvedeni interfejs i da postavim da CustomDelegateListener implementira njega:

Code (php):
interface CListener extends Listener {
  public function add(CustomDelegate $d);
}


Međutim PHP tada kaže Can't inherit abstract function Listener::add() (previously declared abstract in CListener) tj. ne da mi da u izvedenom interfejsu promenim potpis metode, mada mi je malo čudan redosled u ovoj poruci.

Jedino rešenje do koga sam došao (osim da uklonim svuda typehint, što ne želim) je da definišem osnovni interfejs sa svim metodama bez zavisnog typehinta i onda izvedem dva druga interfejsa, jedan za osnovnu i drugi za posebnu klasu:

Code (php):
interface BaseListener {}

interface Listener extends BaseListener {
  public function add(Delegate $d);
}

interface CListener extends BaseListener {
  public function add(CustomDelegate $d);
}


Postoji li lepše rešenje?

Pretragom po vebu došao sam do http://bugs.php.net/bug.php?id=51542&edit=1 i http://p3d.co.uk/blog/?p=88 ali tamo nema korisnih saveta.

[Ovu poruku je menjao Goran Rakić dana 01.10.2010. u 04:07 GMT+1]
http://sr.libreoffice.org — slobodan kancelarijski paket, obrada teksta, tablice,
prezentacije, legalno bez troškova licenciranja
 
Odgovor na temu

Nikola Poša
Backend (PHP) developer
Beograd

Član broj: 173839
Poruke: 1616
*.adsl-a-1.sezampro.yu.



+33 Profil

icon Re: Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."01.10.2010. u 10:13 - pre 165 meseci
Pa izgleda da je nemoguće promeniti potpis metoda nekog interfejsa. Baci pogled na drugi primer na ovoj stranici u manual-u. A mislim da PHP nije izuzetak po tom pitanju, već je to jednostavno jedan od zakona OOP-a.

Možda mi je to promaklo u tvom post-u, ali da li si probao da jednostavno u CustomDelegateListener klasi taj add() metod redefinišeš takav kakav jeste, odnosno, da ga definišeš da prihvata Delegate instancu, baš kao što je to i propisao Listener interfejs? A onda u okviru samog metoda možeš da odradiš još tu dodatnu proveru $d instanceof CustomDelegate, pa da onda ide bacanje izuzetka ili tako nešto, npr.:
Code:
class CustomDelegateListener implements Listener 
{
  public function add(Delegate $d) 
  {
      if (!$d instanceof CustomDelegate) {
          throw new Exception('Invalid param');
      }

      //ostatak kôda
  }
}
 
Odgovor na temu

Goran Rakić
Beograd

Moderator
Član broj: 999
Poruke: 3766

Sajt: blog.goranrakic.com


+125 Profil

icon Re: Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."01.10.2010. u 10:32 - pre 165 meseci
Da, ako ostavim Delegate typehint to je u redu. Rešio sam sa dva interfejsa, ali ipak ću da prebacim na ručnu proveru kako predlažeš jer onda interfejs ostaje ceo i čist kao ugovor sa programerom koji piše kod.

Primer u manualu samo dodaje novu metodu u proširenom interfejsu, ne redefiniše postojeću metodu. Jasno je ograničenje da nasleđeni interfejs ne može da ponavlja metodu u svojoj definiciji. Čak mi je jasno i da moj CustomListener krši dogovor iz Listener interfejsa time što ne prima sve vrste Delegate. Iz perspektive autora jezika to je u redu, ali se potreba nameće u praksi.

Sličan (i teži za rešavanje) problem je i sa ovim kodom koji dodaje novi argument metode:

Code (php):
interface CListener extends Listener {
  public function add(Delegate $d, $hi);
}


ili

Code (php):
class CustomDelegateListener implements Listener {
  public function add(Delegate $d, $hi) { }
}


Jedina mogućnost je da se add() izbaci iz prvog interfejsa (uvede BaseListener koji sadrži sve ostalo, a ovu posebno definišemo u Listener i CListener).
http://sr.libreoffice.org — slobodan kancelarijski paket, obrada teksta, tablice,
prezentacije, legalno bez troškova licenciranja
 
Odgovor na temu

Nikola Poša
Backend (PHP) developer
Beograd

Član broj: 173839
Poruke: 1616
*.adsl-a-1.sezampro.yu.



+33 Profil

icon Re: Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."01.10.2010. u 10:50 - pre 165 meseci
Citat:
Goran Rakić: Primer u manualu samo dodaje novu metodu u proširenom interfejsu, ne redefiniše postojeću metodu.

Ne, ne, baš je u pitanju redefinisanje, pogledaj šta radi klasa d. Najpre primeti da tu postoje dva interfejsa a i b, pri čemu se b izvodi iz a i dodaje metod baz(). A onda klasa d, koja implementira interfejs b, pokušava baz() metodu da promeni tip tog njenog parametra.
 
Odgovor na temu

Goran Rakić
Beograd

Moderator
Član broj: 999
Poruke: 3766

Sajt: blog.goranrakic.com


+125 Profil

icon Re: Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."01.10.2010. u 11:19 - pre 165 meseci
Da, stim što da je Foo izveden iz Bar (kao što je CustomDelegate izveden iz Delegate) ja bih nekako mislio da bi to trebalo da radi ;)
http://sr.libreoffice.org — slobodan kancelarijski paket, obrada teksta, tablice,
prezentacije, legalno bez troškova licenciranja
 
Odgovor na temu

[es] :: PHP :: Nasleđivanje uz strožiji typehint. PHP kaže "must be compatible with ..."

[ Pregleda: 1783 | Odgovora: 4 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.