Ik wil aan sommige classes een functie toevoegen waarmee ik makkelijk kan zien wat de inhoud van de properties is. In 1e instantie was ik van plan om in iedere class (waar nodig) een extra method toe te voegen. Echter, volgens mij kan dat handiger. Ik wil die ene functie in een aparte class zetten (laten we die even class X noemen) en de "hoofd class" dan die class X laten... en nu komt het... extenden???
Ik dacht eigenlijk dat het met implement zou werken...
class Something implements class X
Maar dan krijg ik een foutmelding dat class X een interface moet zijn. Maar als ik er een interface van maak, dan mag ik geen code plaatsen in die extra functie die ik wil maken.
Moet ik dan toch "extends" gebruiken? Ik weet dat Wouter wel eens gezegd heeft dat je extends kunt vervangen door "IS EEN". Die class X wil ik gebruiken om properties te kunnen zijn... maar ik vind het dan raar om te zeggen class ParameterBag IS EEN property viewer. Dat lijkt me niet echt te kloppen... maar met implement lijkt het niet te werken... zie ik iets over het hoofd nu?
Implements en Extends zijn beide parent<>child relaties. Extends voor klassen en implements voor interfaces. Beide mag je dus in zo'n situatie niet gebruiken.
Sinds PHP5.4 hebben we hiervoor Traits, zoek maar eens op.
In OOP kennen we echter ook een "has a" in de vorm van een composite pattern met branches (vertakkingen) en leafs (bladeren). Elke vertakking kan daarbij meerdere bladeren hebben.
Maar even praktisch: je hebt alleen een return get_object_vars($this) nodig.
<?php
class Foo
{
protected $Iets = 'Lorem ipsum';
}
class Bar extends Foo
{
private $NogIets = 'Dolor sit amet';
public function getObjectVars()
{
return get_object_vars($this);
}
}
$object = new Bar();
print_r($object->getObjectVars());
/**
* Array met eigenschappen van Foo en Bar:
Array
(
[NogIets] => Dolor sit amet
[Iets] => Lorem ipsum
)
*/
?>
Ik denk dat je zo'n methode niet zou moeten verheffen tot de norm voor al je klassen om één duidelijke reden: een protected $Iets en een private $NogIets worden prijsgegeven door een public function. Is bijna een terugkerend thema aan het worden :)
Ik wil geen print_r gebruiken, omdat ik er een eigen (nette) opmaak aan meegeef. Het is een soort van luxe debug functie. Er wordt een html pagina getoond met de inhoud van de properties en misschien ook nog wel voor de methods. Voor het programmeren zelf kun je daar verder niks mee.
@Wouter: dankjewel voor de uitleg. Ik had al zo'n vermoeden dat het niet klopte wat ik aan het doen was. De trait werkt perfect! :)
Aha, ik snap het. Dan zou je een constante IN_DEBUG_MODE of IS_ADMIN_FLAG (zo heet dat ding in Zen Cart) kunnen inbouwen die de debugcode alleen bij true uitvoert.
Ik werk niet met zend_cart dus heb geen idee waar je het over hebt :)
Maar ik heb een paar "container" classes. Vantevoren staat niet vast wat daar inzit. Je kunt daar van alles in proppen. Om dan vervolgens gemakkelijk te kunnen zien wat er in ziet wil ik bijv. zoiets kunnen doen:
$this->container->showProperties();
Dat is alles. Normaal gesproken wordt die functie niet gebruikt. Het is puur bedoeld om op een gemakkelijke manier inzichtelijk te krijgen wat er in een class is opgeslagen.
Ik bedoelde een globale constante die je productieomgeving afschermt. In Zen Cart is dat de bool IS_ADMIN_FLAG. En dan zou je dus zoiets krijgen:
<?php
class Bar extends Foo
{
public function getObjectVars()
{
if (IS_ADMIN_FLAG) {
return get_object_vars($this);
} else {
return null;
}
}
}
?>
PHP ondersteunt geen multiple inheritance in de pseudocode-vorm class C extends {A, B}, maar zoals Wouter al aangaf zijn traits daarvan een gedeeltelijke oplossing.
Verder is een nog een dirty trick om multiple inheritance te faken: het kan met method overloading via __call(). Persoonlijk zou ik echter voor de traits gaan. Wouter heeft je al het beste advies gegeven.