在练习测试中有一个有趣的问题,我不明白答案。以下代码的输出是什么:
<?php
class Foo {
public $name = 'Andrew';
public function getName() {
echo $this->name;
}
}
class Bar extends Foo {
public $name = 'John';
public function getName() {
Foo::getName();
}
}
$a = new Bar;
$a->getName();
?>
最初,我认为这会产生错误,因为静态方法无法引用$ this(至少在PHP5中)。我自己测试了它,它实际上输出了约翰。
我添加了Foo :: getName();在脚本的末尾,确实得到了我期待的错误。那么,当你从一个扩展你要调用的类的类中调用静态方法时会发生什么变化呢?
有人会介意详细解释这里发生了什么吗?
答案 0 :(得分:7)
Foo :: getName()使用较旧的PHP4样式scope resolution operator来允许调用重写方法。
在PHP5中,您将使用parent :: getName()而不是
如果你想扩展而不是完全覆盖基类的行为,例如,它是有用的。这可能会更清楚
class Bar extends Foo {
public $name = 'John';
public function getName() {
echo "My name is ";
parent::getName();
}
}
答案 1 :(得分:4)
如果调用绑定到另一个对象的静态方法,则该方法将在当前对象的上下文中执行。这允许访问$ this-object。
从子类内部调用超类方法的更好方法是:
parent::getName();
答案 2 :(得分:2)
$ this到调用该方法的上下文中的对象。所以:$这是$ a-&gt; getName()是$ a。 $ fooInstance-&gt; getName()中的$ this将是$ fooInstance。在$ this设置的情况下(在对象$ a的方法调用中)我们调用静态方法,$ this仍然分配给$ a。
看起来使用此功能可能会产生很多混乱。 :)
答案 3 :(得分:1)
当您致电$a->getName()
时,您正在引用特定对象$a
,该对象属于Bar
类,因此返回“John”。
Foo::getName()
在函数外部无效,因为没有特定的对象。
我不确定它是否适用于PHP,但是如果您将对象强制转换为超级类(Foo)$a->getName()
,那么您将获得“Andrew”作为结果。您仍然在谈论特定对象($a
),但在这种情况下类型为Foo
。 (请注意,您通常不会这样做)
答案 4 :(得分:1)
有时程序员更善于用英语解释内容!
这里首先发生的是重载的概念。当您实例化Bar时,它的getName()方法会重载Foo中同名的方法。
重载是OOD的一个强大而重要的部分。
但是,能够调用Parent类(Foo)中存在的方法的版本通常很有用。
以下是一个例子:
class Dog
{
public function getTag()
{
return "I'm a dog.";
}
}
class Skip extends dog
{
public function getTag()
{
return Dog::getTag() . " My name is Skip.";
// I'm using Dog:: because it matches your example. However, you should use parent:: instead.
}
}
$o = new Skip();
echo $o->getTag(); // Echo's: "I'm a dog. My name is Skip."
显然,这是一个非常狭隘的例子,但它说明了一点。
您的基类是Type的最常规实现。在这种情况下,它是“狗”。您希望将信息放在此基类中,该信息对于该类型的所有实例都是通用的。这可以防止每个派生类中的重复(如“跳过”)。
您的脚本正在利用此功能,可能是无意中。