PHP fóra: Builder | JakPsatWeb | Webtrh
Nejste přihlášen(a)
Zdravím!
Řešil už někdo situaci, kdy je třeba extendovat dvě třídy?
Konkrétně – pracuju na projektu, kde je www sekce postavena na Nette, komunikace s databází není přes db layer, ale přes námi psanou třídu. Tato třída extenduje SoapClient (což je interní třída PHP), ale zároveň by bylo fajn, kdyby mohlo extendovat Object (kvůli fičurkám).
Má toto nějaké řešení?
Thx
A co něco jako:
class MySoapClient extends Nette\Object
{
/** @var SoapClient */
private $soapClient;
…
public function __call($name, $args)
{
$cb = array($this, $name);
if (is_callable($cb)) { // i když u SoapClient to bude asi vždy TRUE, má __call :-/
call_user_func_array($cb, $args);
} else {
parent::__call($name, $args);
}
}
// … __set, __get?
}
Problém je že takovou třídu nelze považovat za potomka
SoapClient, i když se chová skoro totožně.
Editoval LM (9. 1. 2009 22:03)
Tedy, nechci vypadat jako negramota, ale nějak to nechápu…
Tímto by tvoje třída měla vlastnosti třídy Nette\Object a
zároveň by všechny volané metody dál předávala vnitřnímu
SoapClient.
Hm, vzhledem k tomu, že sama o sobě je moje třída dosti složitá, je to dost krkolomné řešení. Budeme se muset vzdát předka Object… Ale to nevadí, trochu jsem s tím počítal, jen jsem to zkusil, jestli náhodou někdo nezná řešení, aby třída měla dva „plnohodnotné“ rodiče.
To (naštěstí) v PHP nejde.
David Grudl napsal(a):
To (naštěstí) v PHP nejde.
To je nižší objektovost :D
Domnivam se, ze reseni od LM by mohlo byt OK. But se zavola metoda Objektu a nebo one druhe tridy. Otazka je nutne dedit? Neslo by jen tvou tridou interne vyuzivat tu druhou. Myslim tim, ze by mela interni instanci kterou by vyuzivala dle potreby.
Jinak „prasacke reseni“ je zkopirovat metody z Object do te tvoji tridy. Moc jich neni:)
Myslím, že řešením může být:
class MySoap extends Object
{
protected $soap;
//...
public function __construct($wsdl,$options)
{
$this->soap = new SoapClient($wsdl,$options);
//...
}
public function __call($method,$args)
{
// Následující kód provede POUZE requesty na server:
return $this->soap->__soapCall($method,$args);
}
// Libovolně lze pak přidat další metody SoapClienta, například:
public function __getFunctions()
{
return $this->soap->__getFunctions();
}
//...
}
Tak to máš samozřejmě špatnej návrh :D
Na manipulační featurky použij návrhovej vzor adapter, takže pak nebude
problém vyměnit soap třeba za db.
Zdedit z dvoch tried sa neda kvoli tzv. ‚Diamond problem‘,
v jednoduchosti diamond problem vznika ak classA a aj classB ma metodu
getFoo(), classC zdedi z oboch tried (classA a classB) ale je tam problem ktoru
getFoo() metodu pouzit/zdedit. Niektore jazyky (Python, Perl etc.) povoluju
dedit aj z viacerych tried a riesia to tymyto sposobmi:
http://en.wikipedia.org/…mond_problem
Ako uz niekto navrhol, pouzi adapter design pattern, alebo pouzivaj interface, v pripade pouzitia interface mozes implementovat viac ako jeden interface, pretoze telo metody nieje specifikovane v interface, takze diamond problem nevznikne.