PHP继承,父函数使用子变量


PHP inheritance, parent functions using child variables

在查看一些PHP代码时,我发现了一件奇怪的事情。下面是一个简单的例子:

文件A.php:

<?php
class A{
    public function methodA(){
        echo $this->B;
    }
}
?>

文件B.php:

<?php
    class B extends A{
        public $B = "It's working!";
    }
?>

文件测试.php:

<?php
    require_once("A.php");
    require_once("B.php");
    $b = new B();
    $b->methodA();
?>

运行test.php会打印出"它在工作!",但问题是为什么它在工作?:)这是一个功能还是一个bug?类A中的方法methodA也可以调用类B中不应在OOP中工作的方法。

您只是在实例化类B。暂时忽略A,并假设methodA()是类B的一部分。

当类B扩展A时,它得到了A的所有函数。$this->B在代码运行之前不会求值,而不是在之前求值。因此,不会发生错误,也不会发生,因为$this->B存在于类B中。

PHP是一种动态语言。方法和数据成员在运行时进行评估。当你调用一个方法或访问一个成员时,PHP实际上会查找一个排序的哈希表,以确定这个方法或成员是否可以在继承层次结构中的任何地方访问。

不仅是继承,您还可以在运行时将任意数据分配给对象,并且类内的代码仍然可以使用$this->something访问它,而类中甚至不存在"something"。

$this只是一个对象变量——一个特殊的变量,因为它是当前的变量,但它仍然只是一个目标变量。

因为$B::B是一个公共成员变量,所以可以从任何可以访问B实例的引用的地方访问它,例如使用对象变量。

由于公共成员在任何地方都可以访问,任何函数,即使是在A::methodA()中也可以访问。

因此,实际上并没有什么值得怀疑的。示例中的类继承仅与调用A::methodA()时以$this"参数"形式传递对象变量(不可见)有关。

请参阅以下可能使其更显眼的示例:

function methodA($object) {
    echo $object->B;
}
class B {
    public $B = "It's working!";
    public function methodA() {
        methodA($this);
    }
}

由于PHP是一种动态语言,调用使用它的实例(在本例中是子类B的实例)上可能存在的属性或方法没有错。

PHP是一种动态语言。当对B的实例调用methodA()时,B的成员$B确实存在。

$a = new A();
$a->methodA();

不会起作用。

在某些动态语言中,您甚至可以在运行时定义方法。

这对我来说很有意义$B由于出现在类B中而在结果对象中可用。由于$this->B是在运行时求值的,并且该值是在此之前设置的(当类B实例化时),因此发现它设置正确。

您也可以对方法执行此操作,因为在执行它们之前不会检查它们的存在性(尽管在方法的情况下,通常在父类中声明它们为抽象的,从而迫使子类实现它们)。

OOP就是这样工作的。一开始这可能看起来有点奇怪,因为你可能认为a必须首先知道$this->B是什么(事实上,在某些语言中,这会产生编译器警告),但行为是正确的,因为你使用的子类定义了函数要查找的变量。如果您从A()的实例调用methodA(),则会得到一个"未定义"错误。

现在,奇怪的是(读起来:错误)如果THIS有效:

class A {
   public $b = "Derp";
}
class B extends A {
  function sayIt() { echo $this->b; }
}
$a = new A();
$a->sayIt();

类B从类A扩展而来,因此它继承了来自类A的方法methodA()