Autor | Zpráva | ||
---|---|---|---|
midlan Profil |
#1 · Zasláno: 13. 8. 2013, 11:48:36
Ahoj,
mám dotaz k dědičnosti. Mám abstraktní třídu, od které dědí další 2 třídy (řekněme A a B). Třída A dědí konstruktor beze změny, ale u třídy B bych potřeboval do konstruktoru přidat jeden parametr. Myslím, že podle pravidel OOP musí zůstat parametry kompatibilní s rodičem, jen se může přidat nějaký nakonec. Jenže to se mi nehodí, protože asi posledních 5 parametrů na konci konstruktoru rodičovské abstraktní třídy jsou parametry s předem vyplněnou hodnotou a v praxi se budou vyplňovat jen vyjímečně. Pokud budu tedy chtít vytvořit instanci třídy B, budu muset vyplňovat všechny parametry, které s největší pravděpodobností jen opíšu, jen kvůli tomu, že jako poslední parametr potřebuji předat instanci. Jde to vyřešit nějak jinak? |
||
noName Profil * |
#2 · Zasláno: 13. 8. 2013, 12:39:30
Můžeš využít setter. Uděláš si metodu
setNeco($neco) { $this->neco = $neco; return $this; } |
||
juriad Profil |
Konstruktory potomků mohou vypadat jakkoli. Prefixem nemusí být parametry konstruktoru předka.
Jediné, co musíš zajistit, je zavolání kontruktoru předka. class Abst { function __construct($x, $y, $z) { echo $x, $y, $z; } } class A extends Abst { function __construct($a, $z, $b, $x) { parent::__construct( $x, 'y', $z); echo $a, $b; } } $a = new A('a', 'z', 'b', 'x'); Klasické dědění metod se netýká konstruktorů, tam platí odlišná pravidla. Note: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. If the child does not define a constructor then it may be inherited from the parent class just like a normal class method (if it was not declared as private). |
||
Joker Profil |
midlan:
Říká se tomu přetěžování metod a PHP to, pokud vím, nepodporuje. edit: ad juriad [#3], je pravda, že s konstruktorem to jde. V PHP to jde udělat přes nepovinný parametr v metodě rodičovské třídy. Jestli ten jeden parametr je potřeba jen na nějakou izolovanou operaci, šlo by ještě udělat separátní metodu, která by tu operaci udělala zvlášť. „asi posledních 5 parametrů na konci konstruktoru“ Kolik jich probůh ten konstruktor má? Obvykle se nedoporučuje dávat metodám příliš mnoho parametrů (jsou případy, kdy je to nutné, ale často je to prostě jen chyba) |
||
Časová prodleva: 5 dní
|
|||
midlan Profil |
#5 · Zasláno: 18. 8. 2013, 15:12:04
juriad:
„Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.“ Ony se snad volají rodičovské metody automaticky, když je v potomkovi přepíšu? Pokaždé musím volat parent::[metoda]() ať už se jedná o metodu kontruktoru nebo normální metodu, nebo ne? Joker: „Jestli ten jeden parametr je potřeba jen na nějakou izolovanou operaci, šlo by ještě udělat separátní metodu, která by tu operaci udělala zvlášť.“ Ne není to je jedna operace, třída s tou instancí bude pracovat neustále. Takže řešením je prostě přeházet si parametry konstruktoru podle potřeby? |
||
juriad Profil |
midlan:
Chtěl jem tím říct, že u metod musíš zajistit identické rozhraní (počet a pořadí parametrů), kdežto u konstruktoru to nutné není. Konstruktor vždy voláš nad konkrétní třídou, tedy víš, jak ten konstruktor vypadá. Pokud je navíc předkem abstraktní třída, tak ta sice konstruktor mít může, ale nikdy jej uživatel nemůže zavolat a tedy znalost jeho rozhraní je pro uživatele neužitečná. Přikláním se k názoru, že rozhraní konstruktorů můžeš volně ale střídmě změnit při dědění. Ale přijde mi rozumné zachovat pořadí parametrů, které zůstaly. Parametr jednoho typu můžeš nahradit (na jeho místě) jedním či více (nenapadá mě přiklad) parametry, pokud je zřejmé, že souvisí/nahrazují původní parametr. A možná bych ještě připustil přesunutí některých parametrů na začátek seznamu. To ale jen za předpokladu, že se jedná o často používané rozhraní, u kterého je k tomu dobrý důvod. Pokud budeš mít hierarchii tříd, které se v celé aplikaci zinstanciují jedinkrát, spíš bych byl konzervativní. Ukážu příklad, který mi přijde rozumný (nehodnotit, zda má takovou hierarchii vůbec smysl budovat a zda právě takto): class FormElem { funmction __construct(string $tagName, string $name, array $values) {} } class Select extends FormElem { function __construct(string $name, array $optionsWithValues, bool $multi) { parent::__construct('select', $name, $optionsWithValues); } } class TextBox extends FormElem { function __construct(string $name, string $placeholder) { parent::__construct('input', $name, array('')); } } |
||
Časová prodleva: 4 dny
|
|||
midlan Profil |
a co říkáš na něco takového:
<?php abstract class Auto { function __construct($nazev, array $vybava = array('klimatizace', 'ABS', 'mlhovky', 'rádio'), $pojizdne = true, $pojistene = false); } class OsobniAuto extends Auto { function __construct($nazev, Ridic $ridic, array $vybava = array('klimatizace', 'ABS', 'mlhovky', 'rádio'), $pojizdne = true, $pojistene = false); } class SamoridiciAuto { #auto se řídí samo, takže nepotřebuje instanci řidiče, konstruktor dědí nepozměněný } |
||
Časová prodleva: 6 dní
|
|||
midlan Profil |
#8 · Zasláno: 29. 8. 2013, 02:05:45
Zhodnotí prosím někdo jestli je mnou uvedený příklad dá považovat za správný?
|
||
juriad Profil |
midlan:
Mě to přijde v pohodě. Jelikož chceš mít povinný parametr $ridic, nezbyde ti nic jiného než ho umístit před ty nepovinné. Ano, mohl bys mu dát výchozí hodnotu NULL a sledovat, zda hodnota se od NULL liší. Nicméně, osobního auto je možné zaparkovat a řidič může vystoupit. Nepřijde mi to proto jako úplně povinný parametr a možná bych šel cestou setteru. Ale klidně to tak měj; poznáš sám během času, zda to byla štastná volba. Refactoring by zas tak složitý nejspíš nebyl. |
||
Kajman Profil |
#10 · Zasláno: 29. 8. 2013, 19:59:01
midlan:
„dá považovat za správný?“ Nemá SamoridiciAuto dědit z Auto? |
||
midlan Profil |
#11 · Zasláno: 31. 8. 2013, 10:52:42
juriad:
Dobře, udělám to tak jak jsem uvedl v příkladu. Tohle není přesný příklad (je to snad dostatečně poznat), ale uvedl jsem stejný počet a typ paramterů, v praxi se bude instance předaná v konstruktoru používat pořád. Kajman: „Nemá SamoridiciAuto dědit z Auto?“ Ano má, moje chyba. |
||
Časová prodleva: 10 let
|
0