constructor
Voorbeeld. Stel we hebben een paths class en we willen (eenmalig) de path prefix instellen, dan lijkt me dit uitermate geschikt om via de constructor te doen:
Code (php)
We hebben nu het voorbereidende werk gedaan, namelijk de path prefix instellen. Prima! Maar, wat zien we nu ook vaak? Dit:
Code (php)
Zoals je ziet is er nu in de constructor een mogelijkheid om direct bij het instantieren van de class een array met paden mee te geven. Hierdoor kunnen we dit doen...
en hoeven we niet dit te doen...
Nu is mijn vraag... als je de $paths direct via de constructor meegeeft, is dat dan eigenlijk wel goed OOP? Is de contructor daar ook echt voor bedoeld?
first and for all:
een constructor kan geen waarde returnen. Hou dat in het achterhoofd. Want wat zou er zoal fout kunnen gaan in het stukje $paths->add()? Het zal je niet lukken om een rechtstreekse foutmelding terug te geven.
dan:
mijn slogan is dat een constructor bedoelt is voor initialisatie. dus de prefix setten in de constructor is prima. als het add() ook enkel het setten van variabelen is dan is dat dus ook prima.
Ooit gehoord van exceptions?
Ozzie, er is geen OO wetboek, maar het is strict genomen voor initialisatie. Dus niet de add() functie. Maar gelukkig zijn we ook nog allemaal developers en geen oo-wetboek-robots en daarom kunnen we lekker de add() functie in de constructor stoppen als we willen.
>> mijn slogan is dat een constructor bedoelt is voor initialisatie. dus de prefix setten in de constructor is prima. als het add() ook enkel het setten van variabelen is dan is dat dus ook prima.
Uhm... en dan is dus de vraag wat initialisatie is. In mijn ogen, maar als het niet klopt verbeter me!, is initialisatie alles wat de class nodig heeft om te kunnen werken. Het prefix path is nodig om de paden te kunnen prefixen, maar het adden van paden zou dan toch nooit in de constructor thuishoren?
resultaat 1 | Het geven van een waarde aan een variabele bij de definitie daarvan. Als je van tevoren al weet welke waarde een variabele moet krijgen, kun je die meteen bij de declaratie een waarde geven. |
resultaat 2 | waarde toekennen aan een gegevensobject aan het begin van zijn levenscyclus |
Gewijzigd op 24/10/2013 01:37:25 door Frank Nietbelangrijk
Stel je hebt een pdf-generator, dan zou je dit kunnen doen:
Code (php)
1
2
3
4
2
3
4
<?php
$pdf = new PDF($data, 'mijn_pdf', '/path/waar/ie/moet/worden/opgeslagen/');
$pdf->generate();
?>
$pdf = new PDF($data, 'mijn_pdf', '/path/waar/ie/moet/worden/opgeslagen/');
$pdf->generate();
?>
Je zou ook dit kunnen doen:
Code (php)
1
2
3
4
2
3
4
<?php
$pdf = new PDF();
$pdf->generate($data, 'mijn_pdf', '/path/waar/ie/moet/worden/opgeslagen/');
?>
$pdf = new PDF();
$pdf->generate($data, 'mijn_pdf', '/path/waar/ie/moet/worden/opgeslagen/');
?>
In voorbeeld 1 wordt alles in de contstructor geset. In voorbeeld 2 wordt het meegegeven aan de method zelf. Mijn idee is dat optie 2 de juiste is. Volgens mij is de constructor alleen bedoeld om de class "gebruiksklaar" te maken.
In mijn eerdere voorbeeldje zou ik dus denken dat het setten van een path prefix thuishoort in een constructor (het "gebruiksklaar" maken van de class), maar het adden van paths niet. Dat is namelijk niet nodig om de class "gebruiksklaar" te maken, en zou dus moeten gebeuren via een aparte add() method.
Kijk jij er ook zo tegenaan?
Beide methodes kunnen juist zijn. Ik lees uit het eerste PDF voorbeeld dat de class bedoeld is om één PDF te genereren. ik bedoel met één dan dat je niet twee verschillende pdf's gaat maken en als je dat wel wilt moet je een tweede instantie van de class aanmaken.
uit het tweede PDF voorbeeld lees ik dat ik maar één keer een PDF class hoef te instantiëren en er vervolgens allerlei verschillende pdf's uit kan genereren. dus dit:
Terug naar m'n paths voorbeeld dan maar weer...
Hoort het zo:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$paths = new Paths($paths_data1); // de constructor roept intern de add($paths) functie aan
// hier wat andere code...
$paths->add($paths_data2);
?>
$paths = new Paths($paths_data1); // de constructor roept intern de add($paths) functie aan
// hier wat andere code...
$paths->add($paths_data2);
?>
... of hoort het zo:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$paths = new Paths();
$paths->add($paths_data1);
// hier wat andere code...
$paths->add($paths_data2);
?>
$paths = new Paths();
$paths->add($paths_data1);
// hier wat andere code...
$paths->add($paths_data2);
?>
In optie 1 geef je data mee die direct in de constructor wordt geset, maar die niet per se nodig is om de class "gebruiksklaar" te maken. Als je die data niet via de constructor meegeeft, dan werkt de class namelijk nog prima. Ik denk daarom dat voorbeeld 2 de juiste (of betere) OO manier is. Begrijp je een beetje wat ik bedoel?
Gewijzigd op 24/10/2013 02:26:03 door Ozzie PHP
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?php
// Duidelijk gestructureerd en overzichtelijk.
$paths = new Paths();
$paths->add($paths_data1);
$paths->add($paths_data2);
// Dit is heel logisch ...
$paths = new Paths($paths_data1);
$paths->add($paths_data2);
// ... als dit ook wordt ondersteund.
$paths = new Paths($paths_data);
?>
// Duidelijk gestructureerd en overzichtelijk.
$paths = new Paths();
$paths->add($paths_data1);
$paths->add($paths_data2);
// Dit is heel logisch ...
$paths = new Paths($paths_data1);
$paths->add($paths_data2);
// ... als dit ook wordt ondersteund.
$paths = new Paths($paths_data);
?>
$paths_data1 en $paths_data2 zijn gewoon arrays waar verschillende paden inzitten (het zijn geen typen)
>> Kun je iets nuttigs doen na new Paths() zonder de methode Paths::add() te gebruiken?
Je moet het zo zien. Met de add method kun je telkens (arrays met) nieuwe paden toevoegen.
Code (php)
Het adden van de paden is in mijn ogen geen wezenlijk onderdeel van het "gebruiksklaar" maken van de class. Want als ik gewoon dit doe:
... dan werkt de class prima, en kan ik gewoon gebruik maken van de add() method. En daarom denk ik dus dat het toevoegen van paden niet thuishoort in de constructor. Ben je het daar mee eens, of niet?
Gewijzigd op 24/10/2013 09:10:39 door Ozzie PHP
Ozzie PHP op 24/10/2013 09:07:46:
Het adden van de paden is in mijn ogen geen wezenlijk onderdeel van het "gebruiksklaar" maken van de class. Want als ik gewoon dit doe:
... dan werkt de class prima, en kan ik gewoon gebruik maken van de add() method. En daarom denk ik dus dat het toevoegen van paden niet thuishoort in de constructor. Ben je het daar mee eens, of niet?
... dan werkt de class prima, en kan ik gewoon gebruik maken van de add() method. En daarom denk ik dus dat het toevoegen van paden niet thuishoort in de constructor. Ben je het daar mee eens, of niet?
Ja en nee. De uiterste consequentie van deze argumentatie is namelijk dat je helemaal nooit een constructor nodig hebt: je kunt immers altijd alles naar methoden delegeren.
Als je na new Paths() slechts een lege huls hebt en je meestal pas na add() iets zinvols kunt doen, dan zou ik de constructor inzetten.
Kijk, in dit geval gebruik je de constructor dus om een class te initialiseren. En volgens mij is dat waar de constructor voor is bedoeld.
Ik snap dat het makkelijk is om via de constructor meteen een paar paden mee te geven, maar wat ik dus wil weten is, is of dat goed OO is. Volgens mij is de constructor (officieel gezien) alleen bedoeld om een class te initialiseren, en niet om "extra" dingen te doen. Maar ik weet het niet zeker. Ik snap dat het heel makkelijk is om iets via de constructor toe te voegen, maar is dat ook de bedoeling van de constructor. Voor iets noodzakelijks als het toevoegen van een path prefix denk ik van wel, maar voor het toevoegen van paden zelf zou ik denken van niet. Dit is dus wat ik graag zou willen weten.
Bij jouw voorbeeld zou ik twee ontwerpbeslissingen laten meespelen.
1. Gebruik je altijd/meestal/vaak onmiddellijk Paths::add() ná new Paths()? Dan zou ik de methode add() toegankelijk maken via de constructor.
2. Kun je iets zinvols doen met het object na new Paths() zonder ooit de methode Paths::add() aan te roepen? Heb je iets aan het object zonder add()? Is het antwoord "Nee", dan zou ik add() ook toegankelijk maken via de constructor — misschien zelfs met een vereist argument als er altijd een pad moet worden opgegeven.
Ja, in feite altijd.
>> 2. Kun je iets zinvols doen met het object na new Paths() zonder ooit de methode Paths::add() aan te roepen?
Nee, want dan zitten er geen paden in. Ik snap nu wel wat je bedoelt... Iets om over na te denken inderdaad :-/
Maar stel je voor: je maakt een Windows programma.
Iets om foto's te resizen of filteren of zo.
Foto's in de GUI slepen; destination settings zetten; op de knop drukken ...
Je zult 200 foto objecten hebben (De fotograaf was nogal trigger happy).
Dan wil je pas zo laat mogelijk de resources in dat object zien; anders neemt dat veel te lang veel te veel geheugen in.
Dus in de constructor initieer je de variabelen die op settings lijken.
bv. het pad van de foto.
Pas wanneer je - 1 voor 1 - de foto's gaat resizen, roep je methode init() aan.
Dan pas maak je je object echt gebruiksklaar.
Zorg trouwens ook voor een methode free()
Je zit met een tijdsduur waar je op moet letten.
Gewijzigd op 24/10/2013 12:01:31 door Kris Peeters
Kris, thanks voor je reactie, maar wat is dan in mijn voorbeeld met de Paths class volgens jou de juiste methode?