2011-06-14 187 views
21

当我尝试重写类变量的方式与重写PHP中的类方法的方式相同。如:PHP变量覆盖

class DataMapper { 
    protected $_name = null; 

    public function printName() { 
      echo $this->_name; 
    } 
} 

class Model extends DataMapper { 
    protected $_name = 'Ana'; 
} 

$test = new Model(); 
$test->printName(); 

这是打印'安娜'。

为什么PHP可以做这样的事情呢?它打破了面向对象范式的规律

+1

我不认为语言行为在任何司法管辖区都是非法的。变量实际上不需要被映射。而在PHP中,对象也是非常简单的字典。你只在这里重新声明默认值。 – mario 2011-06-14 04:56:36

+5

那些不是类变量(即'static'),它们是对象/实例变量。正如人们所解释的,这就是继承应该如何与受保护的成员一起工作。如果你想设置一个私有类变量(即'private static $ myVar ='Ana';'),那么它就不会在任何子类中定义。 – joelhardi 2011-06-14 05:11:04

+0

我理解它的方式,你是对的。您通常不能覆盖变量。在这里,你并没有真的这么做,你只是简单地重新宣布一个变量,而原来的东西却丢失了。反正我觉得呢。 我认为PHP的标准只是稍微宽松一些,并且可以让您摆脱可疑的语法/操作。 – Jonathon 2013-04-17 01:59:20

回答

25

不是。这就是PHP应该如何工作。看看PHP Classes and Objects Visibility

即使它们不是相同的实例,同一类型的对象也可以访问其他私有和受保护的成员。这是因为实现特定的细节在这些对象内部时是已知的。

由于Model扩展了DataMapper,它可以访问它的函数,变量等,但它可以覆盖它们发生的情况。虽然您的函数存在于DataMapper类中,但它是从名称设置为Ana的Model类调用的(并由其继承)。

+0

哇真的很好的答案,我不知道如果PHP可以做到这一点。我已经尝试了C++,C#和JAVA中的相关代码,但没有运气 – brian 2011-06-14 05:06:36

+0

@brian,PHP可以做到这一点,这是一种允许变量覆盖的语言; Java只支持变量隐藏,所以你会得到不同的结果。 – MengT 2014-10-02 08:00:01

3

我不认为这打破了“面向对象的规律”。你已经继承了DataMapper类。因此你已经继承了公共函数printName()。所以当你调用函数时,它就像属于模型类的函数一样。

4

我认为你只是无法理解这是什么。当你引用$ this时,它实际上是引用当前对象。

当您继承DataMapper类时,可以在Model对象内访问printName()方法,但$ this引用仍然引用当前Model对象$ test。

由于Model对象的$ _name属性被实例化为“Ana”,因此它正在打印Ana。这正是预期的。也许再读一遍继承和范围的理论可以帮助你理解这里发生的事情。

+0

是的,但在其他语言像c + +,c#和java它不能这样做。我的意思是覆盖类变量 – brian 2011-06-14 05:12:15

+1

@brian in c#你可以,你只需要明确你打算重写它。否则它只是向下隐藏该范围的父变量。在PHP中的区别是'override'是隐含的。 – drzaus 2013-06-16 19:40:31