Type-Hinting und NULL

Hallo zusammen,

ist das Verhalten so beabsichtigt? Und wenn ja, kann mir jemand erklären
welches Sinn es hat?

<?php
class A {
private $a;
private $b;

public function setA(A $a) {
if($a === null) {
// Special handling since some resources might be released
}

$this->a = $a;
}

public function setB(A $b = null) {
if($b === null) {
// Special handling since some resources might be released
}

$this->b = $b;
}
}

$a = new A();

$a->setB(null); // Funktioniert
$a->setA(null); // Funktioniert nicht
?>

Catchable fatal error: Argument 1 passed to A::setA() must be an
instance of A, null given, called in ... on line 26 and defined in ...
on line 6

--
"Faulheit ist die Wurzel allen Fortschritts!"
(Inhalt eines Knallbonbons, 2002)
dafox [ Do, 10 Januar 2008 00:56 ] [ ID #1904803 ]

Re: Type-Hinting und NULL

On 10 Jan., 00:56, Thomas Hamacher <da... [at] nurfuerspam.de> wrote:
> Hallo zusammen,
>
> ist das Verhalten so beabsichtigt? Und wenn ja, kann mir jemand erklären=

> welches Sinn es hat?
>
> <?php
> class A {
> private $a;
> private $b;
>
> public function setA(A $a) {
> if($a =3D=3D=3D null) {
> // Special handling since some resources might be released
> }
>
> $this->a =3D $a;
> }
>
> public function setB(A $b =3D null) {
> if($b =3D=3D=3D null) {
> // Special handling since some resources might be released
> }
>
> $this->b =3D $b;
> }
>
> }
>
> $a =3D new A();
>
> $a->setB(null); // Funktioniert
> $a->setA(null); // Funktioniert nicht
> ?>
>
> Catchable fatal error: Argument 1 passed to A::setA() must be an
> instance of A, null given, called in ... on line 26 and defined in ...
> on line 6
>
> --
> "Faulheit ist die Wurzel allen Fortschritts!"
> (Inhalt eines Knallbonbons, 2002)

Meiner Meinung nach macht das natürlich keinen Sinn. Ich könnte mich
täuschen, aber afraik ist das ein Bug einer älteren PHP5.x-Version.
Ein Update auf mindestens 5.2 sollte das Problem beheben.

vg
johannes.heinen [ Do, 10 Januar 2008 11:03 ] [ ID #1904808 ]

Re: Type-Hinting und NULL

..oO(johannes.heinen [at] googlemail.com)

>On 10 Jan., 00:56, Thomas Hamacher <da... [at] nurfuerspam.de> wrote:
>> Hallo zusammen,
>>
>> Catchable fatal error: Argument 1 passed to A::setA() must be an
>> instance of A, null given, called in ... on line 26 and defined in ...
>> on line 6
>
>Meiner Meinung nach macht das natürlich keinen Sinn.

Sehe ich im Prinzip auch so, allerdings ist die momentane Implementation
auch durchaus nachvollziebar, denn ein NULL ist nun mal kein Objekt der
geforderten Klasse. Sehr strikt, aber korrekt.

>Ich könnte mich
>täuschen, aber afraik ist das ein Bug einer älteren PHP5.x-Version.
>Ein Update auf mindestens 5.2 sollte das Problem beheben.

Nicht direkt, aber seit 5.2 gibt's E_RECOVERABLE_ERROR, vielleicht läßt
sich damit was drehen, um diesen "Fehler" abzufangen.

Micha
Michael Fesser [ Do, 10 Januar 2008 12:26 ] [ ID #1904809 ]

Re: Type-Hinting und NULL

Michael Fesser:

> Sehe ich im Prinzip auch so, allerdings ist die momentane Implementation
> auch durchaus nachvollziebar, denn ein NULL ist nun mal kein Objekt der
> geforderten Klasse.

Es gibt auch Sichtweisen, bei denen Null zu jeder Klasse gehört. AFAIK ist
das bei UML (bzw. OCLVoid bei OCL) so. Allerdings ist es nie ein echtes
Objekt.
--
Mit PHP Kontonummern auf Gültigkeit prüfen:
<http://bav.malkusch.de/>
Markus Malkusch [ Do, 10 Januar 2008 14:08 ] [ ID #1904810 ]

Re: Type-Hinting und NULL

Michael Fesser schrieb:
> .oO(johannes.heinen [at] googlemail.com)
>
>> On 10 Jan., 00:56, Thomas Hamacher <da... [at] nurfuerspam.de> wrote:
>>> Hallo zusammen,
>>>
>>> Catchable fatal error: Argument 1 passed to A::setA() must be an
>>> instance of A, null given, called in ... on line 26 and defined in ...
>>> on line 6
>> Meiner Meinung nach macht das natürlich keinen Sinn.
>
> Sehe ich im Prinzip auch so, allerdings ist die momentane Implementation
> auch durchaus nachvollziebar, denn ein NULL ist nun mal kein Objekt der
> geforderten Klasse. Sehr strikt, aber korrekt.

Nur wieso dann eine Vorbelegung mit NULL möglich ist, passt nicht.

Wenn man nun den Fall hätte, dass $value immer entweder NULL oder das
gewünschte Objekt ist, müsste man es also so umgehen:

if ($value === NULL) {
foo();
} else {
foo($value);
}

Das ergibt wirklich keinen Sinn, oder?

regards,
Jens
Jens Himmelrath [ Do, 10 Januar 2008 14:14 ] [ ID #1904811 ]

Re: Type-Hinting und NULL

johannes.heinen [at] googlemail.com schrieb:
> On 10 Jan., 00:56, Thomas Hamacher <da... [at] nurfuerspam.de> wrote:

>> ist das Verhalten so beabsichtigt? Und wenn ja, kann mir jemand erklären
>> welches Sinn es hat?

>> Catchable fatal error: Argument 1 passed to A::setA() must be an
>> instance of A, null given, called in ... on line 26 and defined in ...
>> on line 6

> Meiner Meinung nach macht das natürlich keinen Sinn. Ich könnte mich
> täuschen, aber afraik ist das ein Bug einer älteren PHP5.x-Version.
> Ein Update auf mindestens 5.2 sollte das Problem beheben.

Leider nein.

C:\>php -v
PHP 5.3.0-dev (cli) (built: Dec 28 2007 08:19:19)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2007 Zend Technologies

C:\>php tescht.php
Catchable fatal error: Argument 1 passed to A::setA() must be an
instance of A, null given, called in C:\tescht.php on line 26 and
defined in C:\tescht.php on line 6

--
"Faulheit ist die Wurzel allen Fortschritts!"
(Inhalt eines Knallbonbons, 2002)
dafox [ Do, 10 Januar 2008 15:08 ] [ ID #1904815 ]

Re: Type-Hinting und NULL

Jens Himmelrath schrieb:
> Michael Fesser schrieb:
>> Sehe ich im Prinzip auch so, allerdings ist die momentane Implementation
>> auch durchaus nachvollziebar, denn ein NULL ist nun mal kein Objekt der
>> geforderten Klasse. Sehr strikt, aber korrekt.
>
> Nur wieso dann eine Vorbelegung mit NULL möglich ist, passt nicht.

Stimmt, dass ist dann inkonsequent...

> Wenn man nun den Fall hätte, dass $value immer entweder NULL oder das
> gewünschte Objekt ist, müsste man es also so umgehen:
>
> if ($value === NULL) {
> foo();
> } else {
> foo($value);
> }
>
> Das ergibt wirklich keinen Sinn, oder?

Hmm? Was meinst du denn jetzt?

Nochmal zur Klarstellung:
Falls foo als
function foo(A $value = null) {}
definiert ist, dann ist ein Aufruf

$value = null;
foo($value);

durchaus gültig und erzeugt keinen Fehler.


Viele Grüße
Christoph
Christoph Bersch [ Do, 10 Januar 2008 15:54 ] [ ID #1904821 ]

Re: Type-Hinting und NULL

On Thu, 10 Jan 2008 14:14:26 +0100 Jens Himmelrath wrote:
> >>> Catchable fatal error: Argument 1 passed to A::setA() must be an
> >>> instance of A, null given, called in ... on line 26 and defined in ...
> >>> on line 6

> >> Meiner Meinung nach macht das natürlich keinen Sinn.

Meistens nicht. Das erste Mal, als ich darueber gestolpert bin, habe
ich mich auch geaergert.

> wieso dann eine Vorbelegung mit NULL möglich ist, passt nicht.

Doch, durchaus. Die "Vorbelegung" mit NULL ist eine explizite Aussage
darueber, dass an _dieser_ Stelle auch "nichts" uebergeben werden kann.
Somit steht es einem bei jeder Funktion frei, sich neu zu entscheiden,
ob sie NULL-Werte akzeptieren soll oder nicht.

Dokumentiert habe ich das allerdings noch nirgendwo gefunden, bloss als
Anmerkung in den user comments.

> Wenn man nun den Fall hätte, dass $value immer entweder NULL oder das
> gewünschte Objekt ist, müsste man es also so umgehen:

> if ($value === NULL) {
> foo();
> } else {
> foo($value);
> }

Nein, dann schreibe ich einfach

| function foo(ObjectType $value=NULL)

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich

Stefan. Für stumme Keller, wenn der Partner laut muffelt!
(Sloganizer)
Stefan+Usenet [ Do, 10 Januar 2008 16:03 ] [ ID #1904825 ]

Re: Type-Hinting und NULL

Stefan Froehlich schrieb:
> Doch, durchaus. Die "Vorbelegung" mit NULL ist eine explizite Aussage
> darueber, dass an _dieser_ Stelle auch "nichts" uebergeben werden kann.
> Somit steht es einem bei jeder Funktion frei, sich neu zu entscheiden,
> ob sie NULL-Werte akzeptieren soll oder nicht.

Aus diesem Grunde finde ich das Verhalten auch logisch. Ist der Default
nicht angegeben erwartest du ein Objekt der Klasse und es kommt ein
Fehler wenn das nicht geschieht. Ist der Default mit NULL angegeben
drückst du aus, dass NULL (egal ob NULL oder im Sinne von gar nichts)
übergeben werden darf.

> Nein, dann schreibe ich einfach
>
> | function foo(ObjectType $value=NULL)

Dem schließe ich mich an und dem spricht ja auch nicht viel entgegen.
Höchstens dass das Verhalten ungewohnt gegenüber zum Beispiel Java ist.
Allerdings finde ich das Verhalten eher als Vorteil zu betrachten, da
man somit nicht ständig abfragen muss, ob nun wirklich ein Objekt
übergeben wurde, sondern da wo man es erlaubt, kennzeichnet man es.

--
Mit freundlichen Grüßen,
Christoph Herrmann

http://dragonprojects.de/
Christoph Herrmann [ Do, 10 Januar 2008 16:11 ] [ ID #1904826 ]

Re: Type-Hinting und NULL

Thomas Hamacher schrieb:
> ist das Verhalten so beabsichtigt? Und wenn ja, kann mir jemand erklären
> welches Sinn es hat?
>
> public function setA(A $a);
> public function setB(A $b = null);
>
> $a = new A();
>
> $a->setB(null); // Funktioniert
> $a->setA(null); // Funktioniert nicht

Bei setB sagst Du PHP das null ein erlaubter Wert ist da du Ihn als
Default zuweist. (ist übrigens der einzig mögliche Defaultwert)
Null ist ja ansonsten nicht automatisch Bestandteil eines Objekts.

Im Endeffekt macht das aus A $b ein A|null $b.

In irgend einer UCN zum Typehinting für PHP5 im Manual ist dazu auch was
zu finden. Wurde auch schon als Bug gemeldet und daraufhin von PHP-Team
klargestellt. Suchen kannste ja selbst.

MfG, Ulf
Ulf Kadner [ Do, 10 Januar 2008 16:25 ] [ ID #1904827 ]

Re: Type-Hinting und NULL

Ulf Kadner schrieb:
> In irgend einer UCN zum Typehinting für PHP5 im Manual ist dazu auch was
> zu finden. Wurde auch schon als Bug gemeldet und daraufhin von PHP-Team
> klargestellt. Suchen kannste ja selbst.

Klargestellt im Sinne, dass das Verhalten so bestätigt und gewollt ist
oder im Sinne von es wird bald bereinigt, dass es wie in anderen
Sprachen ist? Letzteren fände ich dann doch sehr Nachteilig...

--
Mit freundlichen Grüßen,
Christoph Herrmann

http://dragonprojects.de/
Christoph Herrmann [ Do, 10 Januar 2008 16:33 ] [ ID #1904828 ]

Re: Type-Hinting und NULL

Christoph Herrmann schrieb:

> Klargestellt im Sinne, dass das Verhalten so bestätigt und gewollt ist

genau das. Hab ich ja bereits erklärt.

> oder im Sinne von es wird bald bereinigt, dass es wie in anderen
> Sprachen ist?

Nein natürlich nicht. Es ist kein Problem sondern ein Feature, was ich
im übrigen auch so sehe.

MfG, Ulf
Ulf Kadner [ Do, 10 Januar 2008 16:42 ] [ ID #1904831 ]

Re: Type-Hinting und NULL

..oO(Stefan Froehlich)

>On Thu, 10 Jan 2008 14:14:26 +0100 Jens Himmelrath wrote:
>
>> wieso dann eine Vorbelegung mit NULL möglich ist, passt nicht.
>
>Doch, durchaus. Die "Vorbelegung" mit NULL ist eine explizite Aussage
>darueber, dass an _dieser_ Stelle auch "nichts" uebergeben werden kann.
>Somit steht es einem bei jeder Funktion frei, sich neu zu entscheiden,
>ob sie NULL-Werte akzeptieren soll oder nicht.
>
>Dokumentiert habe ich das allerdings noch nirgendwo gefunden, bloss als
>Anmerkung in den user comments.

Und ich wußte das bis eben noch gar nicht ... tz, wieder was gelernt.
Damit löst sich das ganze Problem ja mehr oder weniger von selbst auf:

function foo(TBar $value)

=> Es muß zwingend ein TBar-Objekt übergeben werden.

function foo(TBar $value = NULL)

=> Es muß entweder ein TBar-Objekt übergeben werden oder gar nichts.

Paßt doch.

Micha
Michael Fesser [ Do, 10 Januar 2008 16:45 ] [ ID #1904833 ]

Re: Type-Hinting und NULL

> Sehe ich im Prinzip auch so, allerdings ist die momentane Implementation
> auch durchaus nachvollziebar, denn ein NULL ist nun mal kein Objekt der
> geforderten Klasse. Sehr strikt, aber korrekt.
In Kombination mit der fehlenden Möglichkeit, Methoden zu überladen, ist
es aber hochgradig blödsinnig.
Jonas Werres [ Do, 10 Januar 2008 20:18 ] [ ID #1904844 ]

Re: Type-Hinting und NULL

> Nein natürlich nicht. Es ist kein Problem sondern ein Feature, was ich
> im übrigen auch so sehe.

Solange es nicht offiziell dokumentiert ist, ist es ein Problem. Denn
solange weiß man nicht, ob sich das Verhalten mal ändert und muss
trotzdem davon ausgehen, null zu bekommen, auch wenn es zur Zeit nicht geht.
Jonas Werres [ Do, 10 Januar 2008 20:21 ] [ ID #1904845 ]

Re: Type-Hinting und NULL

Stefan Froehlich schrieb:
> On Thu, 10 Jan 2008 14:14:26 +0100 Jens Himmelrath wrote:
>>>>> Catchable fatal error: Argument 1 passed to A::setA() must be an
>>>>> instance of A, null given, called in ... on line 26 and defined in ...
>>>>> on line 6
>
>>>> Meiner Meinung nach macht das natürlich keinen Sinn.
>
> Meistens nicht. Das erste Mal, als ich darueber gestolpert bin, habe
> ich mich auch geaergert.
>
>> wieso dann eine Vorbelegung mit NULL möglich ist, passt nicht.
>
> Doch, durchaus. Die "Vorbelegung" mit NULL ist eine explizite Aussage
> darueber, dass an _dieser_ Stelle auch "nichts" uebergeben werden kann.
> Somit steht es einem bei jeder Funktion frei, sich neu zu entscheiden,
> ob sie NULL-Werte akzeptieren soll oder nicht.

Nein, mein Fehler.
Ich konnte mich daran erinnern, dass ich mal den Fall hatte, dass zwar
eine Vorbelegung mit Null möglich war, jedoch kein Aufruf mit Null als
Parameter - ohne das zu überprüfen habe ich in der Nachricht des OP eine
Bestätigung meiner damaligen Feststellung gesehen.

Jetzt habe ich es noch einmal überprüft und kann das Problem nicht
reproduzieren.

> Dokumentiert habe ich das allerdings noch nirgendwo gefunden, bloss als
> Anmerkung in den user comments.
>
>> Wenn man nun den Fall hätte, dass $value immer entweder NULL oder das
>> gewünschte Objekt ist, müsste man es also so umgehen:
>
>> if ($value === NULL) {
>> foo();
>> } else {
>> foo($value);
>> }
>
> Nein, dann schreibe ich einfach
>
> | function foo(ObjectType $value=NULL)

Genau das meinte ich, habe mich nur vertan, weil ich es nicht nochmal
geprüft habe.
Mein Test-Code zeigt nun das damals von mir unverstandene Verhalten
nicht mehr - phpinfo sagt PHP Version 5.2.3-1+b1.

Also, Test-Code:

<?php
error_reporting(E_ALL | E_NOTICE | E_STRICT);

class Test {}
function foo(Test $value = NULL) {}

echo "Parameter: new Test(): ";
foo(new Test());
echo "OK<br/>";


echo "Parameter: \$value (NULL): ";
$value = NULL;
foo($value);
echo "OK<br/>";

echo "Parameter: NULL: ";
foo(NULL);
echo "OK<br/>";

echo "Parameter: 0: ";
foo(0);
echo "OK<br/>";
?>

Output:

Parameter: new Test(): OK
Parameter: $value (NULL): OK
Parameter: NULL: OK
Parameter: 0:

Catchable fatal error: Argument 1 passed to foo() must be an instance of
Test, integer given, called in nullHint.php on line 22 and defined in
nullHint.php on line 5
Jens Himmelrath [ Do, 10 Januar 2008 22:19 ] [ ID #1904850 ]

Re: Type-Hinting und NULL

Jonas Werres schrieb:
>> Nein natürlich nicht. Es ist kein Problem sondern ein Feature, was ich
>> im übrigen auch so sehe.
>
> Solange es nicht offiziell dokumentiert ist, ist es ein Problem.

Nein da Problem ist das Du nicht verstanden hast was ich schrieb...

MfG, Ulf
Ulf Kadner [ Fr, 11 Januar 2008 10:51 ] [ ID #1905599 ]

Re: Type-Hinting und NULL

On 10 Jan., 15:08, Thomas Hamacher <da... [at] nurfuerspam.de> wrote:
> johannes.hei... [at] googlemail.com schrieb:
>
> > On 10 Jan., 00:56, Thomas Hamacher <da... [at] nurfuerspam.de> wrote:
> >> ist das Verhalten so beabsichtigt? Und wenn ja, kann mir jemand erklä=
ren
> >> welches Sinn es hat?
> >> Catchable fatal error: Argument 1 passed to A::setA() must be an
> >> instance of A, null given, called in ... on line 26 and defined in ...
> >> on line 6
> > Meiner Meinung nach macht das natürlich keinen Sinn. Ich könnte mich=

> > täuschen, aber afraik ist das ein Bug einer älteren PHP5.x-Version.
> > Ein Update auf mindestens 5.2 sollte das Problem beheben.
>
> Leider nein.
>
> C:\>php -v
> PHP 5.3.0-dev (cli) (built: Dec 28 2007 08:19:19)
> Copyright (c) 1997-2007 The PHP Group
> Zend Engine v2.3.0, Copyright (c) 1998-2007 Zend Technologies
>
> C:\>php tescht.php
> Catchable fatal error: Argument 1 passed to A::setA() must be an
> instance of A, null given, called in C:\tescht.php on line 26 and
> defined in C:\tescht.php on line 6
>
> --
> "Faulheit ist die Wurzel allen Fortschritts!"
> (Inhalt eines Knallbonbons, 2002)

Stimmt auch. Ich hatte mich verlesen und es mit einem Problem in
Zusammenhang gebracht, welches in einer frühen PHP-Version 5 auftrat,
welche auch bei =DCberladung mit function setA ( A $instanceOfA =3D null )
einen fatal-error ausrotzte (nämlich genau den von Dir beschriebenen),
und zwar in beiden Fällen des Aufrufs ( setA (null) und setA() ).

Das von Dir beschriebene Verhalten bei Aufruf von setB(B
$instanceOfB ) mittels setB(null) finde ich aus der Gewohnheit heraus
nicht ungewöhnlich. Wenn man das mit Java vergleicht, ists aber
komisch, hier kann durchaus ein Null-Pointer übergeben werden.
Wahrscheinlich liegts einfach daran, dass die Mechanismen zur
=DCberladung doch recht unterschiedlich sind, wenn man es unter dem
Gescihtspunkt betrachtet, ist die Umsetzung in PHP vlt doch ganz
sinnvoll und auch nützlich, so kann man die =DCbergabe von null-Werten
als Objektzeiger explizit verbieten. Ich sehe es darum auch eher als
feature denn als bug.

vg johannes
johannes.heinen [ Fr, 11 Januar 2008 11:27 ] [ ID #1905600 ]

Re: Type-Hinting und NULL

> Nein da Problem ist das Du nicht verstanden hast was ich schrieb...

Dann erleuchte mich.
Jonas Werres [ Fr, 11 Januar 2008 21:49 ] [ ID #1905607 ]
PHP » de.comp.lang.php.misc » Type-Hinting und NULL

Vorheriges Thema: Werkzeug zur Visualisierung von Includes
Nächstes Thema: Apache Auth nutzen