Type Hinting und optionale Parameter
Blaubart
- php
0 dedlfix
0 Andreas Görtz
'Nabend.
Ich bin gerade beim Zusammenspiel von Type Hinting und optionalen Funktionsparametern in PHP 5 über ein Problem gestolpert, das ich nicht gelöst kriege. Dazu folgendes Beispiel:
class Foo {
function foobar (Foo $foo, Bar $bar, $baz = 0) {
echo 'Foobar!';
}
}
class Bar {
function blupp() {
echo 'Blupp!';
}
}
$bar = new Bar();
$foo = new Foo();
$foo->foobar($foo, null, 1);
NULL ist offensichtlich nicht einsetzbar als eine Art Platzhalter für "leere" Objekte, analog zu '' bei Strings -- oder eben der Nullpointer in anderen Sprachen. PHP meckert mit einem "Fatal error: Argument 2 passed to Foo::foobar() must not be null".
Setze ich als zweite Variante im Funktionskopf...
function foobar (Foo $foo, Bar $bar = null, $baz = 0)
... gibt es das Gemecker nicht mehr in PHP 5.1, aber dafür in Version 5.0. Ob das tatsächlich von der Version abhängt oder doch an einem Unterschied in der Konfiguration liegt, konnte ich bisher nicht herausfinden.
Gibt es einen vernünftigen[TM] Weg, um ein Objekt in der Parameterliste wahlweise auszulassen oder anders eindeutig als Sonderfall zu kennzeichnen? $foo->foobar($foo, , 1) kann ich ja auch nicht schreiben -- weder für Objekte noch Primitivtypen. Solange ich nicht herausgefunden habe, woher die unterschiedlichen Reaktionen bei der zweiten Variante (s.o.) kommen, seh ich eigentlich nur den umständlichen Umweg über ein selbstgestricktes Dummyobjekt. Und _das_ möchte ich wirklich gerne vermeiden. ;)
echo $begrüßung;
function foobar (Foo $foo, Bar $bar, $baz = 0) {
$foo->foobar($foo, null, 1);
NULL ist offensichtlich nicht einsetzbar als eine Art Platzhalter für "leere" Objekte, analog zu '' bei Strings [...] PHP meckert mit einem "Fatal error: Argument 2 passed to Foo::foobar() must not be null".
null ist ein anderer Typ als object (oder in diesem Fall Bar) und entspricht deshalb nicht der Type-Hint-Vorgabe.
oder eben der Nullpointer in anderen Sprachen.
PHP ist PHP. Andere Sprachen sind andere Sprachen.
Setze ich als zweite Variante im Funktionskopf...
function foobar (Foo $foo, Bar $bar = null, $baz = 0)
... gibt es das Gemecker nicht mehr in PHP 5.1, aber dafür in Version 5.0. Ob das tatsächlich von der Version abhängt oder doch an einem Unterschied in der Konfiguration liegt, konnte ich bisher nicht herausfinden.
PHP-Changelog Version 5.1.0: "Changed type hints to allow "null" as default value for class and array."
Gibt es einen vernünftigen[TM] Weg, um ein Objekt in der Parameterliste wahlweise auszulassen oder anders eindeutig als Sonderfall zu kennzeichnen?
Was spricht denn gegen die Defaultwert-Angabe?
echo "$verabschiedung $name";
Hallo dedlfix.
oder eben der Nullpointer in anderen Sprachen.
PHP ist PHP. Andere Sprachen sind andere Sprachen.
Ist mir klar. Es sollte -- wie ich auch schrieb -- eine Analogie sein, damit klar ist, was ich meine.
Was spricht denn gegen die Defaultwert-Angabe?
Die durch deinen Link bestätigte Tatsache, daß diese Methode erst ab PHP 5.1 einsetzbar ist, welches ich aber nicht überall als gegeben voraussetzen kann.
echo $begrüßung;
Was spricht denn gegen die Defaultwert-Angabe?
Die durch deinen Link bestätigte Tatsache, daß diese Methode erst ab PHP 5.1 einsetzbar ist, welches ich aber nicht überall als gegeben voraussetzen kann.
Dann hast du in meinen Augen zwei Möglichkeiten:
Letzteres bevorzugte ich. Mit dem gleichen Verfügbarkeitsargument müsstest du PHP5-Spezifisches komplett ausklammern, da das schließlich auch noch nicht überall vorausgesetzt werden kann ...
echo "$verabschiedung $name";
Moin!
Letzteres bevorzugte ich. Mit dem gleichen Verfügbarkeitsargument müsstest du PHP5-Spezifisches komplett ausklammern, da das schließlich auch noch nicht überall vorausgesetzt werden kann ...
Und das ist nichts neues, sowas hat es schon bei Sprung von 4.0 zu 4.1 gegeben ($HTTP_GET_VARS -> $_GET war da der größte Effekt), und danach in kleinen Details und Funktionen auch bei jedem weiteren Versionswechsel. Wirklich drum kümmern tun sich darum lediglich die großen Softwarepakete wie phpMyAdmin, der kleine Programmierer geht da einfach stillschweigend drüber hinweg. :)
- Sven Rautenberg
Hi,
der kleine Programmierer geht da einfach stillschweigend drüber hinweg. :)
Einspruch euer Ehren! ;-)
Gruß, Cybaer
Hi Blaubart,
Gibt es einen vernünftigen[TM] Weg, um ein Objekt in der Parameterliste wahlweise auszulassen oder anders eindeutig als Sonderfall zu kennzeichnen?
Du könntest in der Deklaration die Parameter 2 und 3 weglassen und diese bei Existenz selbst prüfen:
class Foo {
function foobar (Foo $foo) {
$bar = null;
if (func_num_args() > 1) {
$bar = func_get_arg(1);
if (!is_null($bar) && !is_a($bar, 'Bar')) {
trigger_error('Argument 2 must be an object of class Bar', E_USER_ERROR);
}
}
}
}
Ob das vernünftig ist - ich weiß es nicht ;-)
Gruß,
Andreas.
Hallo Andreas.
Du könntest in der Deklaration die Parameter 2 und 3 weglassen und diese bei Existenz selbst prüfen:
Interessante Alternative. Ich werd mir mal überlegen, ob es sich lohnt, das konsequent umzusetzen oder doch lieber die Aufgabenstellung anzupassen. ;)
echo $begrüßung;
Hallo Andreas.
Du könntest in der Deklaration die Parameter 2 und 3 weglassen und diese bei Existenz selbst prüfen:
Interessante Alternative. Ich werd mir mal überlegen, ob es sich lohnt, das konsequent umzusetzen oder doch lieber die Aufgabenstellung anzupassen. ;)
Parameter in der Funktionsdeklaration auszulassen und stattdessen über func_get_arg darauf zugreifen ist zwar ein von PHP vorgesehener Weg, den ich aber nur als Ausnahme von der Regel ansehen möchte. Er trägt aber nicht gerade dazu bei, dass diese Programmstelle leichter zu lesen ist. Ich empfehle, in dem Fall die Parameter ohne Type-Hint anzugeben. Eine Typüberprüfung mit is_a()/instanceof *) ist in beiden Fällen erforderlich/angebracht, und den Type-Hint wegzulassen ist deutlich übersichtlicher als die func_get_arg-Methode. Den Aufwand sollte man lieber in eine Dokumentation stecken.**)
/**
* Allgemeine Funktionsbeschreibung
*
* @param Bar $bar Kurzbeschreibung von bar
* @param Baz/null $baz ...
* @param integer $bal ...
* @return type
*/
function foo(Bar $bar, $baz, $bal) {
if ($baz === null or $baz instanceof Baz)
...
echo "$verabschiedung $name";
*) is_a() ist die PHP4-Variante und unter PHP5 deprecated. PHP5 bietet dagegen den instanceof-Operator.
**) Entwicklungsumgebungen mit PHPDoc-Unterstützung wissen diese Art Dokumentation zu schätzen. Und Anwender dieser Entwicklungsumgebungen freuen sich ebenfalls darüber.
Hallo dedlfix.
Parameter in der Funktionsdeklaration auszulassen und stattdessen über func_get_arg darauf zugreifen ist zwar ein von PHP vorgesehener Weg, den ich aber nur als Ausnahme von der Regel ansehen möchte. Er trägt aber nicht gerade dazu bei, dass diese Programmstelle leichter zu lesen ist.
Sehe ich auch so. Deshalb zögere ich bisher mit der Umsetzung dieser Variante. Da ich aber generell meine Funktionen, Klassen etc. nach PHPDoc dokumentiere, wäre die Übersicht nicht _komplett_ verloren, auch wenn in meinen Augen Parameterlisten in den Funktionskopf gehören.
Ich empfehle, in dem Fall die Parameter ohne Type-Hint anzugeben.
Ich denke, genau das werde ich tun. Verbunden mit einer Typenprüfung zu Beginn der Funktion.
Danke euch.