PHP变量重写

PHP变量重写,php,overriding,oop,Php,Overriding,Oop,当我试图以与PHP中重写class方法相同的方式重写class变量时。比如: class DataMapper { protected $_name = null; public function printName() { echo $this->_name; } } class Model extends DataMapper { protected $_name = 'Ana'; } $test = new Model

当我试图以与PHP中重写class方法相同的方式重写class变量时。比如:

class DataMapper {
     protected $_name = null;

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

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

$test = new Model();
$test->printName();
这是印刷品“安娜”


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

我不认为这违反了“面向对象法则”。您已经继承了DataMapper类。因此,您继承了公共函数printName()。因此,当调用函数时,它的行为与属于模型类的函数类似

不是。这就是PHP应该如何工作的。看一看

相同类型的对象将有权访问彼此的私有成员和受保护成员,即使它们不是相同的实例。这是因为在这些对象中,特定于实现的细节是已知的


因为模型扩展了DataMapper,所以它可以访问它的函数、变量等,但它可以覆盖它们,这就是发生的情况。虽然您的函数位于DataMapper类中,但它是从名称设置为Ana的模型类调用(并由该模型类继承)的。

我认为您在理解$this的功能时遇到了问题。引用$this时,它实际上是在引用当前对象

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


由于模型对象的$\u name属性被实例化为“Ana”,因此正在打印Ana。这正是人们所期望的。也许再通读一下继承和范围的理论会帮助你理解这里发生了什么。

我不认为这种语言行为在任何司法管辖区都是非法的。变量实际上不需要阴影。在PHP中,对象也是非常简单的字典。此处仅重新声明默认值。这些不是类变量(即
静态
),而是对象/实例变量。正如人们所解释的,这就是继承应该如何与受保护的成员一起工作。如果您改为设置私有类变量(即,
private static$myVar='Ana';
),那么它不会在任何子类中定义。按照我的理解,您是对的。通常不能覆盖变量。在这里,你并不是真的这么做,你只是重新定义了一个变量,原来的变量就丢失了。我想,无论如何。我认为PHP只是在标准上有点松散,可以让您摆脱有问题的语法/操作。哇,答案真不错,我想知道PHP是否可以做到这一点。我已经尝试过C++、C语言和java中的相关代码,但是没有luck@brian,PHP可以做到这一点,这是一种允许变量重写的语言;java只支持变量隐藏,所以你得到的结果不同。是的,但是在C++、C语言和java等语言中,它不能做到这一点。我的意思是说,我的意思是凌驾于课堂之上variable@brian在c#中,您可以,您只需明确表示您打算覆盖它。否则,它只是从该范围向下隐藏父变量。PHP的不同之处在于,
覆盖
是隐式的。