简体   繁体   English

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

[英]PHP inheritance, parent functions using child variables

While reviewing some PHP code I've discovered a strange thing. 在查看一些PHP代码时,我发现了一件奇怪的事情。 Here is the simple example illustration of it: 以下是它的简单示例说明:

File A.php: 文件A.php:

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

File B.php: 文件B.php:

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

File test.php: 文件test.php:

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

Running test.php prints out "It's working!", but question is why is it working? 运行test.php打印出“它正在工作!”,但问题是它为什么有效? :) Is this a feature or a bug? :)这是一个功能还是一个bug? Method methodA in class A can also call methods that are in class B which should not work in OOP. 类A中的方法方法A也可以调用B类中不应该在OOP中工作的方法。

You're only instantiating class B . 你只是在实例化B类。 Ignore A for the moment, and pretend that methodA() is part of class B . 暂时忽略A ,并假装methodA()B类的一部分。

When class B extends A , it gets all of A 's functions. B类扩展A ,它获得A的所有功能。 $this->B isn't evaluated until the code is running, not prior. $this->B在代码运行之前不会被评估,而不是之前。 Therefore no error occurs, and won't occur as $this->B exists in class B . 因此不会发生错误,并且作为不会发生$this->B类存在B

PHP is a dynamic language. PHP是一种动态语言。 The methods and data members are evaluated at runtime. 方法和数据成员在运行时进行评估。 When you call a method or access a member, PHP actually looks up a hashtable of sort to find out whether this method or member can be accessed on this object or not which can be anywhere in the inheritance hierarchy. 当您调用方法或访问成员时,PHP实际上会查找排序的哈希表,以确定是否可以在此对象上访问此方法或成员,这可以是继承层次结构中的任何位置。

And not just inheritance, you can always assign arbitrary data to an object on runtime and the code inside the class will still be able to access it using $this->something where 'something' didn't even exist in class. 而且不仅仅是继承,你总是可以在运行时将任意数据分配给一个对象,并且类中的代码仍然可以使用$ this->某些东西来访问它,其中“某些东西”甚至不存在于类中。

$this is just an object variable - a special one because it's the current one, but it still is just an object variable. $this只是一个对象变量 - 一个特殊的变量,因为它是当前变量,但它仍然只是一个对象变量。

Because $B::B is a public member variable, it can be accessed from everwhere a reference to the instance of B is reachable, eg with a object variable. 因为$B::B是一个公共成员变量,所以可以从任何地方访问对B实例的引用,例如使用对象变量。

As public members are accessible everywhere, any function, even from within A::methodA() it can be accessed. 由于公共成员随处可访问,因此即使在A::methodA()也可以访问任何函数。

So there is not much to actually wonder about. 所以实际上并不奇怪。 Class inheritance in your example only relates to the (invisible) passing of the object variable in form of the $this "parameter" when A::methodA() is invoked. 您的示例中的类继承仅涉及在调用A::methodA()时以$this “参数”的形式传递对象变量的(不可见)。

See the following example that probably makes it more visible: 请参阅以下示例,该示例可能使其更加明显:

function methodA($object) {
    echo $object->B;
}

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

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

PHP is a dynamic language. PHP是一种动态语言。 When methodA() is called on an instance of B the B's member $B does actually exist. 当在B的实例上调用methodA()时,B的成员$ B确实存在。

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

would not work. 不行。

In some dynamic languages you can even define methods at runtime. 在某些动态语言中,您甚至可以在运行时定义方法。

That makes sense to me; 这对我有意义; $B is made available in the resultant object by virtue of its appearing in class B. Since $this->B is evaluated at run-time, and the value is set before that (when class B is instantiated) it is found to be set correctly. 由于出现在B类中,$ B在结果对象中可用。因为$ this-> B在运行时被计算,并且在此之前设置了值(当B类被实例化时),它被发现是设置正确。

You can do this with methods as well, since their existence is not checked until they are executed (although it is usual in the case of methods to declare them abstract in the parent class, thus forcing the child to implement them). 您也可以使用方法执行此操作,因为它们的存在在执行之前不会被检查(尽管通常在方法的情况下在父类中声明它们是抽象的,因此强制子项实现它们)。

This is how OOP is supposed to work. 这就是OOP的工作方式。 It might seem a little odd at first, since you'd think that A would have to know what $this->B is first (and indeed in some languages this would produce a compiler warning), but the behavior is correct since the subclass you're using is defining the variable that your function is looking for. 起初看起来有点奇怪,因为你认为A必须知道$this->B是第一个(实际上在某些语言中这会产生编译器警告),但行为是正确的,因为子类你正在使用的是定义你的函数正在寻找的变量。 If you called methodA() from an instance of A() , then you'd get an "undefined" error. 如果从A()的实例调用methodA() ,则会出现“未定义”错误。

Now, what would be weird (read: wrong ) is if THIS worked: 现在,奇怪的是(读: 错误 )如果有效:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM