PHP 允许在其他语言中产生编译错误的多态代码。一个简单的例子说明了这一点。第一个产生预期编译错误的 C++ 代码:
class Base {};
class CommonDerivedBase {
public:
// The "= 0" makes the method and class abstract
// virtual means polymorphic method
virtual whoami() = 0;
};
class DerivedBase : public CommonDerivedBase {
public:
void whoami() { cout << "I am DerivedBase \n"; }
};
class Derived1 : public CommonDerivedBase {
public:
void whoami() { cout << "I am Derived1\n"; }
};
class Derived2 : public CommonDerivedBase {
public:
void whoami() { cout << "I am Derived2\n"; }
};
/* This will not compile */
void test_error(Base& db)
{
db.whoami();
}
C++ 编译器将针对行db.whoami() 发出此错误消息
error: no member named 'whoami' in 'Base'
因为 Base 没有名为 whoami() 的方法。然而,类似的 PHP 代码直到运行时才发现此类错误。
class Base {}
abstract class DerivedCommonBase {
abstract function whoami();
}
class Derived1 extends DerivedCommonBase {
public function whoami() { echo "I am Derived1\n"; }
}
class Derived2 extends DerivedCommonBase {
public function whoami() { echo "I am Derived2\n"; }
}
/* In PHP, test(Base $b) does not give a runtime error, as long as the object
* passed at run time derives from Base and implements whoami().
*/
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); //<-- A run time error will result.
foreach 循环与输出一起工作
I am Derived1
I am Derived2
在您调用 test($b) 并传递 Base 实例之前,您不会收到运行时错误。所以在foreach之后,输出会是
I am Derived1
I am Derived2
PHP Fatal error: Call to undefined method Base::whoami() in
home/kurt/public_html/spl/observer/test.php on line 22
关于使 PHP 更安全的唯一方法是添加运行时检查
测试 $b 是否是您想要的类的实例。
function test(Base $b)
{
if ($b instanceof DerivedCommonBase) {
$b->whoami();
}
}
但多态性的全部意义在于消除此类运行时检查。