Ola,

Ik heb een basis-class Foo. Ik wil dat iedere class die class Foo extend de private method foobar() heeft.

Nu heb ik van de class Foo een abstract class gemaakt, waarin staat:

abstract private function foobar();

Nu krijg ik een foutmelding:

abstract function foobar() cannot be declared private in...

Waarom kan ik geen private abstracte methods maken? Of doe ik iets verkeerd?
Hum het zou toch ook geen zin hebben? Je kunt immers geen private functie overschrijven. Privé is privé en daar blijft de rest van de wereld af.

Waarom gebruik je geen interface?
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.
Weet je wel wat je nu zegt?
Stel BMW heeft ook fietsen, maar een fiets heeft een protected class fietsbel. Vul het zelf maar in....
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?
Als je het vanuit de constructor aanroept waarom dan niet

<?php

public abstract class foo {

public function construct() {
bar();
}

private function bar() {
//
}

}
?>

en dan vanuit je child klasses je parent construct aanroepen?
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:

Even jou gequote uit een ander topic:

Wouter J op 01/11/2013 14:58:29

<?php
class FileNotFoundException extends FileException
{
public function __construct($filename, $message = '', $code = 0, \Exception $previous = null)
{
parent::__construct(
sprintf('Cannot find file "%s"%s', $filename, ';'.$message ?: ''),
$code,
$previous,
);
}
}
?>

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 hoop dat je het nu beter begrijpt.
Ozzie PHP op 02/11/2013 00:05:50

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 />

Reageren