Ik ben net begonnen met (lezen van) een boek over OOP en kom er nu al niet uit. Hopelijk kan iemand mij uitleggen wat ik verkeerd doe. Ik zeg er bij dat er geen opdrachten in het boek zitten, maar dat ik wel alle scripts uitschrijf en dan evt uitbreidt aan de hand van de stof om er zoveel mogelijk van op te pikken.
Het voorbeeld hieronder is trouwens een voorbeeld van hoe het niet moet maar dat staat los van mijn probleem. (volgende alinea gaat over inheritance en moet ik leren hoe het wel moet, haha)
Het boek laat een class zien met de naam ShopProduct. In deze class kun je zowel boeken als cd's aanmaken. Via de omslachtige functie getType moet je testen of je met een boek of cd te maken hebt. Deze functie wordt in het boek niet voorgedaan en heb ik dus zelf geschreven. De rest van de code komt letterlijk uit het boek, behalve dan dat aan getSummaryLine een extra regel (ik kan helemaal geen type vinden) heb toegevoegd om wat meer inzicht te krijgen in wat er nou mis gaat.)
De output van dit script is dus "ik kan helemaal geen type vinden". Dus ik vermoed dat er iets mis gaat in de functie getType. Echter, helemaal onderaan het script print ik bij wijze van test functie getType en dan krijg ik wel als output "book". Ik snap dus niet waarom functie getSummaryLine niet vaststelt dat het om een boek gaat.
Alvast mijn excuses als ik iets heel doms gedaan heb maar werk voor het eerst met classes dus moet nog heel veel leren...
<?php
class ShopProduct {
public $numPages;
public $playLength;
public $title;
public $producerMainName;
public $producerFirstName;
public $price;
public $type;
function getNumberOfPages() {
return $this->numPages;
}
function getPlayLength() {
return $this->playLength;
}
function getProducer() {
return "{$this->producerFirstName}"."{$this->producerMainName}";
}
function getType() {
if ($this->numPages != 0){
$this->type = "book";
} else {
$this->type = "cd";
}
return $this->type;
}
function getSummaryLine() {
$base = "{$this->title} ( {$this->producerMainName}, ";
$base .= "{$this->producerFirstName} )";
if ($this->type == "book" ) {
$base .= ": page count - {$this->numPages}";
} else if ( $this->type == "cd" ) {
$base .= ": playing time - {$this->playLength}";
} else {
$base .= "ik kan helemaal geen type vinden";
}
return $base;
}
}
$product1 = new shopProduct("Boek over PHP", "Matt", "Zandstra", 5.99, 235, 0);
print $product1->getSummaryLine();
print $product1->getType();
?>
[size=xsmall]Toevoeging op 24/10/2016 14:06:35:[/size]
Als aanvulling, als ik $type gewoon in de contruct functie toevoeg werkt het wel maar het idee is juist dat het aan de hand van $numPages bepaald moet worden...
getType() aanroepen in je functie mag best, maar dan meer als
<?php
$type = $this->getType();
?>
Wanneer je toch bepaalt op basis van $this->numPages heb je in principe dan $this->type niet nodig. Het voelt hooguit wat vreemd om op basis van het aantal pagina's het type te bepalen. Hoe classificeer je een dubbelcd bijvoorbeeld?
Je kunt uiteraard ook in de functie setNumPages bepalen wat het type wordt, en dan getType() binnen de class niet gebruiken. Het is maar net wat in de huidige situatie handiger is. Er is geen 1 formule die alles dekt.
Hier staat de logica van je klasse: als iets pagina's heeft, is het een boek. Je zou die logica kunnen verplaatsen naar de constructor, aangezien je dáár (en alleen daar) het aantal pagina's instelt:
Dank jullie, Ward, ik bedoelde inderdaad precies wat jij hier laat zien! Het is me nu duidelijk! (ik had niet door dat ik dat stukje code in de functie __construct kon/moest zetten)
Nogmaals, dat er allemaal haken en ogen aan kleven om op deze manier te bepalen of het om een boek of cd gaat (en wat dan als er ineens ook nog een dubbel cd zoals Ben van Velzen zegt bij zou komen ofzo) dat weet ik, ga nu verder met de paragraaf over hoe het dan wel moet. Maar door dit stukje besefte ik dat ik eea niet helemaal begreep en nu begrijp ik het wel. Dus ik kan weer verder, bedankt! :)
In principe heb je bij de constructie van het object alle informatie om te bepalen van welk type deze is, dus hiervoor hoef je niet per se een aparte setter te maken. Het tweede codevoorbeeld van @Ward (de uitgebreide __construct) zou dus ook mijn voorkeur hebben.
Te meer om het volgende: objecten zijn (zouden?) meestal gebruiksklaar (moeten zijn?) na constructie. Dit houdt tevens in dat alle klasse-variabelen geïnitialiseerd zouden moeten zijn (een beginwaarde ontvangen zouden moeten hebben). Jouw probleem ontstond juist doordat $this->type nog geen waarde had op het moment dat je deze wilde gaan gebruiken in de methode getSummaryLine().
Het is altijd verstandig om elke (klasse-)variabele te voorzien van een (expliciete,) initiële waarde.
>> Het boek laat een class zien met de naam ShopProduct. In deze class kun je zowel boeken als cd's aanmaken.
Dat lijkt me al vreemd, dat je een algemene class gebruikt om een specifiek product aan te maken. Ward gaf dit eerder ook al aan zie ik.
Door dit soort rare voorbeelden zou je dus met één en dezelfde class een bankstel en een vliegtuig kunnen aanmaken (want een vliegtuig heeft 2 vleugels ... hmmm, juist ja). Als je het mij vraagt, leer je door dit soort voorbeelden niet goed programmeren.
In de realiteit zul je dus eerder gaan werken als volgt:
<?php
$book = new Book();
$cd = new Cd();
$car = new Car();
?>
Het is heel raar om een object aan te maken, en vervolgens aan dat object te moeten vragen 'zeg ehhh ... wat ben jij eigenlijk voor een object?'.
Te meer om het volgende: objecten zijn (zouden?) meestal gebruiksklaar (moeten zijn?) na constructie. Dit houdt tevens in dat alle klasse-variabelen geïnitialiseerd zouden moeten zijn (een beginwaarde ontvangen zouden moeten hebben). Jouw probleem ontstond juist doordat $this->type nog geen waarde had op het moment dat je deze wilde gaan gebruiken in de methode getSummaryLine().
Het is altijd verstandig om elke (klasse-)variabele te voorzien van een (expliciete,) initiële waarde.
Duidelijk verhaal! dank je :)
[size=xsmall]Toevoeging op 25/10/2016 16:59:00:[/size]
Ozzie PHP op 25/10/2016 16:40:34
Even terug naar het begin ...
>> Het boek laat een class zien met de naam ShopProduct. In deze class kun je zowel boeken als cd's aanmaken.
Dat lijkt me al vreemd, dat je een algemene class gebruikt om een specifiek product aan te maken. Ward gaf dit eerder ook al aan zie ik.
Door dit soort rare voorbeelden zou je dus met één en dezelfde class een bankstel en een vliegtuig kunnen aanmaken (want een vliegtuig heeft 2 vleugels ... hmmm, juist ja). Als je het mij vraagt, leer je door dit soort voorbeelden niet goed programmeren.
In de realiteit zul je dus eerder gaan werken als volgt:
<?php
$book = new Book();
$cd = new Cd();
$car = new Car();
?>
Het is heel raar om een object aan te maken, en vervolgens aan dat object te moeten vragen 'zeg ehhh ... wat ben jij eigenlijk voor een object?'.
Ozzie, je hebt helemaal gelijk.Zoals ik als aangaf, dit script is een voorbeeld van waarom het niet handig is om een class te maken die meerdere verschillende objecten denkt die allemaal verschillende eigenschappen hebben. (ben bezig met 'PHP Objects, Patterns, and Practice van Matt Zandstra') Volgende alinea houdt zich er mee bezig hoe dat beter kan. Maar omdat ik hier even vastliep omdat ik de $type er niet in kreeg wilde ik dat eerst even duidelijk hebben voor mezelf, voor ik in het volgende stuk duik. En hier nog vragen over had.
Het is jammer dat er geen opdrachten met uitleg bij het boek zitten, er wordt een stuk code gegeven en daar dan bij gezegd dat je de $type property kan instellen door $numPages te testen, maar nergens staat hoe. Dat probeerde ik dus voor elkaar te krijgen.
Ik gaf het alleen even aan omdat er genoeg boeken zijn die met dit soort foute voorbeelden strooien en het zou jammer zijn als jij vervolgens denkt 'dat het zo hoort' en het dus ook zo gaat doen.
>> ... kan instellen door $numPages te testen, maar nergens staat hoe.
Dat is iets waar je aan zult moeten wennen bij computerboeken. Vaak zijn die geschreven door programmeurs die niet altijd even goed in staat zijn om vanuit het perspectief van een beginner naar hun eigen code te kijken, laat staan met een kritische blik naar hun eigen code te kijken. Ik ben nog nooit een computerboek tegengekomen waar geen fouten in staan. Het probleem is dat je die fouten als beginner niet herkent en je dus geen idee hebt wat je fout doet. Als je wat meer gevorderd bent, herken je zulke fouten wel en kun je je alleen maar afvragen waarom de auteur iets heeft opgeschreven en klaarblijkelijk niet heeft getest.
Anyhow ... lang verhaal kort: verbaas je niet over fouten in computerboeken. En als je ergens niet uitkomt dan horen we het wel weer ;-)