|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits              [2015-03-07 10:50 UTC] reeze@php.net
 
-Status:      Open
+Status:      Closed
-Assigned To:
+Assigned To: reeze
  [2015-03-07 10:50 UTC] reeze@php.net
 | |||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 14:00:01 2025 UTC | 
Description: ------------ It seems to me, there is some unclear situation with keywords «self» (and «parent»). At least this keywords has no detailed documentation. Imaging following interface: interface IFoo { public function lorem(IFoo $foo); public function ipsum(self $foo); } The first method lorem() wants an implementation of IFoo as argument. The one problem here is a duplication of the name IFoo inside itself. Usage of keyword «self» should prevent this "problem", but in theory only. The second method ipsum() extects an instance of... of what? In fact, it wants an instance of «self» - that is an instance of implementation class, which implements or even overrides the method later. The problem is the fact, that keyword «self» means SELF, not a class or an interface, there it is writen. We cannot change «self» to «IFoo» in implementation: interface IFoo { public function ipsum(self $foo); } class Fail implements IFoo { public function ipsum(IFoo $foo) { } } // Error: Fail::ipsum() must be compatible with IFoo::ipsum() The ReflectionClass shows «IFoo», «self» and «parent» for corresponding methods: interface IFoo { public function lorem(IFoo $foo); public function ipsum(self $foo); public function dolor(parent $foo); } $ref = new ReflectionClass('IFoo'); echo $ref; Output: Method [ <user> abstract public method lorem ] { - Parameters [1] { Parameter #0 [ <required> IFoo $foo ] } } Method [ <user> abstract public method ipsum ] { - Parameters [1] { Parameter #0 [ <required> self $foo ] } } Method [ <user> abstract public method dolor ] { - Parameters [1] { Parameter #0 [ <required> parent $foo ] } } When we write «self» somewhere, we mean that thing, where «self» is writen. I think, that method ipsum() should be compiled to receive instance of IFoo and nothing else. The method dolor() shoult to emit fatal error, because IFoo has no parent. If I mistake with that deep meaning if the keywords «self» and «parent», and this isn't a bug, I sure this keywords should be documented properly. Test script: --------------- interface IFoo { public function ipsum(self $foo); } class Bar implements IFoo { public function ipsum(self $foo) { echo __METHOD__, "(", get_class($foo), ")\n"; } } class Baz extends Bar { public function ipsum(self $foo) { echo __METHOD__, "(", get_class($foo), ")\n"; } } class Lol implements IFoo { public function ipsum(self $foo) { echo __METHOD__, "(", get_class($foo), ")\n"; } } # test objects $bar = new Bar(); $baz = new Baz(); $lol = new Lol(); # lets try everything # IFoo::ipsum(self $foo) # Bar::ipsum(self $foo) $bar->ipsum($bar); # Bar::ipsum(Bar) $bar->ipsum($baz); # Bar::ipsum(Baz) $bar->ipsum($lol); # Error: Bar::ipsum() extects Bar, but Lol given # Baz::ipsum(self $foo) $baz->ipsum($bar); # Error: Baz::ipsum() extects Baz, but Bar given $baz->ipsum($baz); # Baz::ipsum(Baz) $baz->ipsum($lol); # Error: Baz::ipsum() extects Baz, but Lol given # Lol::ipsum(self $foo) $lol->ipsum($bar); # Error: Lol::ipsum() extects Lol, but Bar given $lol->ipsum($baz); # Error: Lol::ipsum() extects Lol, but Baz given $lol->ipsum($lol); # Lol::ipsum(Lol) Expected result: ---------------- Bar::ipsum(Bar) Bar::ipsum(Baz) Bar::ipsum(Lol) Baz::ipsum(Bar) Baz::ipsum(Baz) Baz::ipsum(Lol) Lol::ipsum(Bar) Lol::ipsum(Baz) Lol::ipsum(Lol) Actual result: -------------- Bar::ipsum(Bar) Bar::ipsum(Baz) Catchable fatal error: Argument 1 passed to Bar::ipsum() must be an instance of Bar, instance of Lol given, called in ... and defined ...