Re: Why is polymorphism in PHP not like other languages? Is there a bug in PHP? [message #185132 is a reply to message #185128] |
Thu, 27 February 2014 22:06 |
Thomas 'PointedEars'
Messages: 701 Registered: October 2010
Karma:
|
Senior Member |
|
|
kurtk(at)pobox(dot)com wrote:
> Thanks for all the replies. I could probably have simplified the example,
> like this
>
> <?php
> class Base {}
>
> class DerivedCommonBase extends Base {
> public function whoami() { echo "I am DerivedCommonBase\n"; }
> }
>
> class Derived1 extends Base {
> public function whoami() { echo "I am Derived1\n"; }
> }
>
> class Derived2 extends Base {
> public function whoami() { echo "I am Derived2\n"; }
> }
>
> // Base has not whoami() method...
> function test(Base $b) { $b->whoami(); }
>
> $b = new Base();
> $d1 = new Derived1();
> $d2 = new Derived2();
>
> $a = array();
>
> $a[] = $d1;
> $a[] = $d2;
>
> foreach($a as $x) {
> echo test($x);
> }
>
> test($d1);
> test($d2);
> test($b); // <--...this is detected at run time
What do you mean by that?
> However, I did learn that in PHP you can pass a derived class to a method
> that takes a base class and then invoke a method that does not exist in
> the base class. Derived1 is a DerivedCommonBase is a Base. Something with
> Derived2. But somehow PHP knows the final subtype $b within method
> test(Base $b).
Nonsense. As expected, the code that you posted *fails to execute properly*
reproducibly here:
,----
| $ php -r 'class Base {}
| >
| > class DerivedCommonBase extends Base {
| > public function whoami() { echo "I am DerivedCommonBase\n"; }
| > }
| >
| > class Derived1 extends Base {
| > public function whoami() { echo "I am Derived1\n"; }
| > }
| >
| > class Derived2 extends Base {
| > public function whoami() { echo "I am Derived2\n"; }
| > }
| >
| > // Base has not whoami() method...
| > function test(Base $b) { $b->whoami(); }
| >
| > $b = new Base();
| > $d1 = new Derived1();
| > $d2 = new Derived2();
| >
| > $a = array();
| >
| > $a[] = $d1;
| > $a[] = $d2;
| >
| > foreach($a as $x) {
| > echo test($x);
| > }
| >
| > test($d1);
| > test($d2);
| > test($b);'
| I am Derived1
| I am Derived2
| I am Derived1
| I am Derived2
| PHP Fatal error: Call to undefined method Base::whoami() in Command line
code on line 16
| PHP Stack trace:
| PHP 1. {main}() Command line code:0
| PHP 2. test() Command line code:33
|
| $ php -v
| PHP 5.5.9-1 (cli) (built: Feb 8 2014 00:52:52)
| Copyright (c) 1997-2014 The PHP Group
| Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
| with XCache v3.1.0, Copyright (c) 2005-2013, by mOo
| with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend
Technologies
| with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans
| with XCache Optimizer v3.1.0, Copyright (c) 2005-2013, by mOo
| with XCache Cacher v3.1.0, Copyright (c) 2005-2013, by mOo
| with XCache Coverager v3.1.0, Copyright (c) 2005-2013, by mOo
`----
You are not passing a class, and the method does not take a class (nor would
it in C++ where you appear to be coming from). You are passing a reference
to an object (not to be confused with a reference to a variable or array
element), and that is what the function takes.
AFAIK, C++ uses static type-checking: your C++ program does not compile if
the call cannot be matched to a template. PHP uses dynamic type-checking
instead: the type of a symbol is determined at runtime (after compilation,
upon execution of the statement).
The class name in the function/method declaration/definition is a *type
hint*. It means that the object whose reference is passed to the
function/method must have be an instance of this class or its class must
have the specified class as superclass, or it must implement the specified
interface if the identifier is that of an interface:
<http://php.net/manual/en/language.oop5.typehinting.php>
Obviously, this criterion is met here; however, “$b” refers to an instance
of “Base” and those objects do not have a whoami() method; hence the error
message. Whatever you may have observed instead has nothing to do with the
code that you posted.
PointedEars
--
When all you know is jQuery, every problem looks $(olvable).
|
|
|