There was an interesting question in a practice test that I did not understand the answer to. What is the output of the following code:
在练习测试中有一个有趣的问题,我不明白答案。以下代码的输出是什么:
<?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();
?>
Initially, I thought this was produce an error because static methods can not reference $this (atleast in PHP5). I tested this myself and it actually outputs John.
最初,我认为这会产生错误,因为静态方法不能引用$ this(至少在PHP5中)。我自己测试了这个,它实际上输出了约翰。
I added Foo::getName(); at the end of the script and did get the error I was expecting. So, what changes when you call a static method from within a class that extends the class you're calling from?
我添加了Foo :: getName();在脚本的末尾,确实得到了我期待的错误。那么,当你从一个扩展你正在调用的类的类中调用静态方法时会发生什么变化?
Would anyone mind explaining in detail exactly what is going on here?
谁会介意详细解释这里发生了什么?
5 个解决方案
#1
$this to the object in whose context the method was called. So: $this is $a->getName() is $a. $this in $fooInstance->getName() would be $fooInstance. In the case that $this is set (in an object $a's method call) and we call a static method, $this remains assigned to $a.
$ this到调用该方法的上下文中的对象。所以:$这是$ a-> getName()是$ a。 $ fooInstance-> getName()中的$ this将是$ fooInstance。在$ this设置的情况下(在对象$ a的方法调用中)并且我们调用静态方法,$ this仍然分配给$ a。
Seems like quite a lot of confusion could come out of using this feature. :)
看起来使用此功能可能会产生很多混乱。 :)
#2
Foo::getName() is using an older PHP4 style of scope resolution operator to allow an overridden method to be called.
Foo :: getName()使用较旧的PHP4样式的作用域解析运算符来允许调用重写的方法。
In PHP5 you would use parent::getName() instead
在PHP5中,您将使用parent :: getName()
It's useful if you want to extend, rather than completely override the behaviour of the base class, e.g. this might make it clearer
如果你想扩展而不是完全覆盖基类的行为,例如,它是有用的。这可能会让它更清晰
class Bar extends Foo {
public $name = 'John';
public function getName() {
echo "My name is ";
parent::getName();
}
}
#3
If you call the static method bound to the other object, the method is executed in the context of the current object. Which allows access to the $this-object.
如果调用绑定到另一个对象的静态方法,则该方法将在当前对象的上下文中执行。这允许访问$ this-object。
Better way to call the superclass-method from inside the subclass would be:
从子类内部调用超类方法的更好方法是:
parent::getName();
#4
When you call $a->getName()
you're referencing a specific object, $a
, which is of class Bar
and so returns "John".
当你调用$ a-> getName()时,你引用了一个特定的对象$ a,它是类Bar,所以返回“John”。
Foo::getName()
isn't valid outside the function because there's no specific object.
Foo :: getName()在函数外部无效,因为没有特定的对象。
I'm not sure it works in PHP, but if you cast the object to the superclass as in (Foo)$a->getName()
then you'd get "Andrew" as your result. You'd still be talking about the specific object ($a
) but in this case of type Foo
. (Note you wouldn't generally want to do this)
我不确定它是否适用于PHP,但是如果你将对象转换为超类,如(Foo)$ a-> getName()那么你将获得“Andrew”作为结果。你仍然在谈论特定的对象($ a),但在这种情况下类型为Foo。 (注意你一般不想这样做)
#5
Sometimes programmers are better at explaining things in code than in English!
有时程序员更善于用英语解释代码中的东西!
The first thing going on here is the concept of overloading. When you instantiate Bar, it's getName() method overloads the method of the same name in Foo.
这里首先发生的是重载的概念。当您实例化Bar时,它的getName()方法会重载Foo中同名的方法。
Overloading is a powerful and important part of OOD.
重载是OOD的一个强大而重要的部分。
However, it is often useful to be able to call the version of a method that exists in the Parent class (Foo).
但是,能够调用Parent类(Foo)中存在的方法的版本通常很有用。
Here's an example:
这是一个例子:
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."
Clearly this is a very parochial example but it illustrates a point.
显然,这是一个非常狭隘的例子,但它说明了一点。
Your base class is the most general implementation of a Type. In this case, it's "Dog." You want to put information in this base class that is common to all instances of that Type. This prevents duplication in each of the Derived classes (like "Skip").
您的基类是Type的最常规实现。在这种情况下,它是“狗”。您希望将信息放在此基类中,该信息对于该类型的所有实例都是通用的。这可以防止每个派生类中的重复(如“跳过”)。
Your script is taking advantage of this feature, perhaps inadvertently.
您的脚本正在利用此功能,可能是无意中。
#1
$this to the object in whose context the method was called. So: $this is $a->getName() is $a. $this in $fooInstance->getName() would be $fooInstance. In the case that $this is set (in an object $a's method call) and we call a static method, $this remains assigned to $a.
$ this到调用该方法的上下文中的对象。所以:$这是$ a-> getName()是$ a。 $ fooInstance-> getName()中的$ this将是$ fooInstance。在$ this设置的情况下(在对象$ a的方法调用中)并且我们调用静态方法,$ this仍然分配给$ a。
Seems like quite a lot of confusion could come out of using this feature. :)
看起来使用此功能可能会产生很多混乱。 :)
#2
Foo::getName() is using an older PHP4 style of scope resolution operator to allow an overridden method to be called.
Foo :: getName()使用较旧的PHP4样式的作用域解析运算符来允许调用重写的方法。
In PHP5 you would use parent::getName() instead
在PHP5中,您将使用parent :: getName()
It's useful if you want to extend, rather than completely override the behaviour of the base class, e.g. this might make it clearer
如果你想扩展而不是完全覆盖基类的行为,例如,它是有用的。这可能会让它更清晰
class Bar extends Foo {
public $name = 'John';
public function getName() {
echo "My name is ";
parent::getName();
}
}
#3
If you call the static method bound to the other object, the method is executed in the context of the current object. Which allows access to the $this-object.
如果调用绑定到另一个对象的静态方法,则该方法将在当前对象的上下文中执行。这允许访问$ this-object。
Better way to call the superclass-method from inside the subclass would be:
从子类内部调用超类方法的更好方法是:
parent::getName();
#4
When you call $a->getName()
you're referencing a specific object, $a
, which is of class Bar
and so returns "John".
当你调用$ a-> getName()时,你引用了一个特定的对象$ a,它是类Bar,所以返回“John”。
Foo::getName()
isn't valid outside the function because there's no specific object.
Foo :: getName()在函数外部无效,因为没有特定的对象。
I'm not sure it works in PHP, but if you cast the object to the superclass as in (Foo)$a->getName()
then you'd get "Andrew" as your result. You'd still be talking about the specific object ($a
) but in this case of type Foo
. (Note you wouldn't generally want to do this)
我不确定它是否适用于PHP,但是如果你将对象转换为超类,如(Foo)$ a-> getName()那么你将获得“Andrew”作为结果。你仍然在谈论特定的对象($ a),但在这种情况下类型为Foo。 (注意你一般不想这样做)
#5
Sometimes programmers are better at explaining things in code than in English!
有时程序员更善于用英语解释代码中的东西!
The first thing going on here is the concept of overloading. When you instantiate Bar, it's getName() method overloads the method of the same name in Foo.
这里首先发生的是重载的概念。当您实例化Bar时,它的getName()方法会重载Foo中同名的方法。
Overloading is a powerful and important part of OOD.
重载是OOD的一个强大而重要的部分。
However, it is often useful to be able to call the version of a method that exists in the Parent class (Foo).
但是,能够调用Parent类(Foo)中存在的方法的版本通常很有用。
Here's an example:
这是一个例子:
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."
Clearly this is a very parochial example but it illustrates a point.
显然,这是一个非常狭隘的例子,但它说明了一点。
Your base class is the most general implementation of a Type. In this case, it's "Dog." You want to put information in this base class that is common to all instances of that Type. This prevents duplication in each of the Derived classes (like "Skip").
您的基类是Type的最常规实现。在这种情况下,它是“狗”。您希望将信息放在此基类中,该信息对于该类型的所有实例都是通用的。这可以防止每个派生类中的重复(如“跳过”)。
Your script is taking advantage of this feature, perhaps inadvertently.
您的脚本正在利用此功能,可能是无意中。