Type-Hinting und NULL

Type-Hinting und NULL

am 10.01.2008 00:56:43 von dafox

Hallo zusammen,

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

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)

Re: Type-Hinting und NULL

am 10.01.2008 11:03:32 von johannes.heinen

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

> welches Sinn es hat?
>
> > class A {
> private $a;
> private $b;
>
> public function setA(A $a) {
> if($a ===3D null) {
> // Special handling since some resources might be released
> }
>
> $this->a =3D $a;
> }
>
> public function setB(A $b =3D null) {
> if($b ===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

Re: Type-Hinting und NULL

am 10.01.2008 12:26:00 von Michael Fesser

..oO(johannes.heinen@googlemail.com)

>On 10 Jan., 00:56, Thomas Hamacher 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

Re: Type-Hinting und NULL

am 10.01.2008 14:08:22 von Markus Malkusch

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:

Re: Type-Hinting und NULL

am 10.01.2008 14:14:26 von Jens Himmelrath

Michael Fesser schrieb:
> .oO(johannes.heinen@googlemail.com)
>
>> On 10 Jan., 00:56, Thomas Hamacher 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

Re: Type-Hinting und NULL

am 10.01.2008 15:08:14 von dafox

johannes.heinen@googlemail.com schrieb:
> On 10 Jan., 00:56, Thomas Hamacher 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)

Re: Type-Hinting und NULL

am 10.01.2008 15:54:36 von Christoph Bersch

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

Re: Type-Hinting und NULL

am 10.01.2008 16:03:58 von Stefan+Usenet

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)

Re: Type-Hinting und NULL

am 10.01.2008 16:11:58 von Christoph Herrmann

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/

Re: Type-Hinting und NULL

am 10.01.2008 16:25:28 von Ulf Kadner

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

Re: Type-Hinting und NULL

am 10.01.2008 16:33:50 von Christoph Herrmann

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/

Re: Type-Hinting und NULL

am 10.01.2008 16:42:42 von Ulf Kadner

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

Re: Type-Hinting und NULL

am 10.01.2008 16:45:25 von Michael Fesser

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

Re: Type-Hinting und NULL

am 10.01.2008 20:18:09 von Jonas Werres

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

Re: Type-Hinting und NULL

am 10.01.2008 20:21:13 von Jonas Werres

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

Re: Type-Hinting und NULL

am 10.01.2008 22:19:46 von Jens Himmelrath

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:

error_reporting(E_ALL | E_NOTICE | E_STRICT);

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

echo "Parameter: new Test(): ";
foo(new Test());
echo "OK
";


echo "Parameter: \$value (NULL): ";
$value = NULL;
foo($value);
echo "OK
";

echo "Parameter: NULL: ";
foo(NULL);
echo "OK
";

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

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

Re: Type-Hinting und NULL

am 11.01.2008 10:51:15 von Ulf Kadner

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

Re: Type-Hinting und NULL

am 11.01.2008 11:27:54 von johannes.heinen

On 10 Jan., 15:08, Thomas Hamacher wrote:
> johannes.hei...@googlemail.com schrieb:
>
> > On 10 Jan., 00:56, Thomas Hamacher 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 Überladung 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
Überladung 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 Übergabe von null-Werten
als Objektzeiger explizit verbieten. Ich sehe es darum auch eher als
feature denn als bug.

vg johannes

Re: Type-Hinting und NULL

am 11.01.2008 21:49:42 von Jonas Werres

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

Dann erleuchte mich.