Dat was mijn eerste idee ook Frank, maar ook hier kan ik geen private methods declareren (ook wel logisch eigenlijk). Dus daarom dacht ik een abstract class te gaan gebruiken.
Maar als ik het dus goed begrijp kan ik nooit een private method forceren?
Interfaces en abstracte methods moeten worden gezien als een contract. Een klaase houdt zich aan het contract door ten minste de benodigde methods te hebben.
Nu wil jij een contract maken voor een private method. Een private method, wweet je nog? Die kun je alleen via de klasse zelf aanroepen. Je gaat dus een contract met jezelf maken. Alsof je een contract zou maken voor het werk dat jij nu doet voor je framework. Dat doe je niet, want dat is pure onzin. Zo is het in PHP ook.
En PHP helpt je gelukkig om onzin code te voorkomen door een error te gooien.
>> Een private method, wweet je nog? Die kun je alleen via de klasse zelf aanroepen
Oke, dat was ook exact mijn bedoeling :) Ik wil dus forceren dat ik in iedere class die specifieke method moet hebben staan, zodat ik die niet vergeet. Ik zie dat het wel werkt als ik de method protected maak.
Om nog even terug te komen op wat jij zegt... waarom is het zo raar eigenlijk om een private method te forceren? Ik wil die method vanuit de constructor triggeren... ja natuurlijk, ik kan de code ook meteen in de constructor zetten, maar ik vind het duidelijker als ik het in een aparte method zet. Dat PHP dat niet toestaat... vooruit, maar dat jij het bestempelt als pure onzin.. mwa.. vind ik een beetje overdreven.
Stel dat ik een autobouwer ben van het merk BMW, en we beschouwen de auto als een class. Dan zou ik willen forceren dat iedere auto van het merk BMW een startonderbreker heeft. Dit apparaat is uitsluitend vanuit de auto (class) zelf bereikbaar. Het is dan heel prettig als er een blauwdruk ligt waarin staat dat iedere auto een startonderbreker heeft, zodat die nooit kan worden vergeten.
Anyhow... wat ik wil gaat dus niet. En dat was eigenlijk mijn vraag.
Hehehe, Ger... ik denk dat je een punt probeert te maken, alleen ik volg ff niet welk punt :)
>> Stel BMW heeft ook fietsen
Euhhh... oke... :P
>> maar een fiets heeft een protected class fietsbel
Een protected class??? Tja, ehh...
(Er van uitgaande dat je een method bedoelt... een fietsbel moet je van buitenaf bij kunnen, dus die maak je uiteraard public.)
>> Vul het zelf maar in....
Misschien kun jij dat beter even doen :) Jouw kennende zul je zeker een goed punt hebben, alleen ik zie het niet... dus vertel, wat bedoel je te zeggen?
Ozzie, vanuit de abstracte class kun je geen private method aanroepen. Dus "ik roep hem aan in de constructor" betekend dat je die method in de constructor van de child class aanroept. Dan is het volledig zijn zorgen. De contracten in OO zijn bedoeld voor de buitenwereld. Stel je voor een abstracte class gebruikt ergens de getRegex method, deze zal moeten worden geïmplementeerd door de child class. Dan maak je deze method abstract, zodat je zeker weet dat je geen 'undefined method getRegex' error krijgt.
Hetzelfde werkt met interfaces, zodra ik weet dat een object een bepaalt interface heeft kan ik er altijd van uitgaan dat die methods bestaan en ik die methods kan gebruiken zonder dat ik 'undefined method' errors krijg.
Hoe die methods er uitzien en wat die klasse vanbinnen doet maakt het andere object niks uit, daar mag hij zelfs helemaal niks over weten. Hij mag alleen weten dat die methods die in het contract staan aanwezig zijn.
Geef eens een echt voorbeeld waarin je dit wilt toepassen. Want ik ben bang dat je of het woord abstract of het woord private niet begrijpt...
Ik zal het voorbeeld geven. Ik heb dus een eigen "default" exception class, voor het gemak noem ik die nu even MyDefaultException. Deze extend de PPH Exception class.
Nu was mijn bedoeling om met custom Exception classes te gaan werken, bijv. een FileSystemException. Deze extend dan de MyDefaultException class.
Wat ik wilde doen is mezelf verplichten om voor iedere custom Exception class een "mooi" bericht te maken, op basis van de message die wordt meegegeven aan de constructor. Eigenlijk hetzelfde wat jij ook doet, alleen jij doet dit in de constructor:
Wat jij hier doet in de constructor... sprintf('Cannot find file "%s"%s', $filename, ';'.$message ?: '') ... dat wil ik in een method stoppen die door de constructor wordt aangeroepen. Waarom? Om het voor mezelf wat overzichtelijker te houden wat er in de code gebeurt. Mijn idee was dus (grofweg) zeg maar dit:
<?php
class FileSystemException extends MyDefaultException {
public function __construct($message, $code = 0, Exception $previous = null)
parent::construct($this->setMessage($message), $code, $previous);
}
// Set the message.
private function setMessage($message) {
$message = 'The FileSystem experienced an exception:<br>' . $message;
return $message;
}
}
// en dan ergens in de filesystem class...
if ('bestand kan niet worden geschreven') {
throw FileSystemException('The file ' . $file . ' could not be written.');
}
?>
Ik wil dus een setMessage() method forceren zodat ik altijd verplicht ben om een mooie/nette "message" op te stellen. Door deze method te verplichten, kan ik het ook nooit vergeten. En waarom deze method private is... omdat ik die niet van buitenaf wil kunnen aanroepen.
Ik wil dus een setMessage() method forceren zodat ik altijd verplicht ben om een mooie/nette "message" op te stellen. Door deze method te verplichten, kan ik het ook nooit vergeten. En waarom deze method private is... omdat ik die niet van buitenaf wil kunnen aanroepen.
Maak dan $message in de constructor een vereist argument. Zoals in example #2 in de PHP Manual.
<?php
throw new FileSystemException('File not found.', 404);
class FileSystemException extends Exception
{
public function __construct($message, $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
?>
Hoewel $message slechts de string 'File not found.' bevat, krijg je een gedetailleerde melding inclusief stack trace. Heb je hier echt niet genoeg aan?
<br />
<b>Fatal error</b>: Uncaught exception 'FileSystemException' with message 'File not found.' in C:\pad\naar\index.php:2
Stack trace:
#0 {main}
thrown in <b>C:\pad\naar\index.php</b> on line <b>2</b><br />