Home  >  Article  >  Backend Development  >  this 在继承的类中指向父类?

this 在继承的类中指向父类?

WBOY
WBOYOriginal
2016-06-23 14:19:021220browse

<?phpclass pa{    private function m(){        echo 'Parent\'s function';    }    public function run(){        $this->m();    }}class child extends pa{    public function m(){        echo 'child\'s function';    }}$obj=new child();$obj->run();


你们猜,结果是什么,居然是parents function,可是,m()方法没有被继承因为protected,run()集成到了子类,那么方法里面的this应该指向子类实例,调用子类m方法,结果却调用了,父类的m方法,如果把private改成public,则调用子类方法m,谁能解释一下


回复讨论(解决方案)

没有找到更详细的解释extends作用机理的文章,以下只是我的猜测

我觉得造成这种问题的原因可能在于,虽然表面上是继承了父类,但是父类实际上是存在的,也就是说,如果通过子类的实例化对象来调用父类中的某个方法,那么实际上它进入到了父类的空间里,那么在父类空间里的$this的作用范围就是父类空间本身,而不能跨越到子类的空间中。

之所以会这么猜想,是因为PHP的变量的引用原理,也就是当一个变量的值,是另一个变量的引用时,并不等同于这两个变量变成了同一个变量,其实本身还是两个变量,并且销毁其中一个的时候,另一个仍然存在。

所以基于此我认为,子类的实例化对象不应该使用父类中的$this来代表子类的对象,这样会造成对象的“越级”

还是那句话:私有的是不可侵犯的

楼上回复真心精辟啊!

没有找到更详细的解释extends作用机理的文章,以下只是我的猜测

我觉得造成这种问题的原因可能在于,虽然表面上是继承了父类,但是父类实际上是存在的,也就是说,如果通过子类的实例化对象来调用父类中的某个方法,那么实际上它进入到了父类的空间里,那么在父类空间里的$this的作用范围就是父类空间本身,而不能跨越到子类的空间中。

之所以会这么猜想,是因为PHP的变量的引用原理,也就是当一个变量的值,是另一个变量的引用时,并不等同于这两个变量变成了同一个变量,其实本身还是两个变量,并且销毁其中一个的时候,另一个仍然存在。

所以基于此我认为,子类的实例化对象不应该使用父类中的$this来代表子类的对象,这样会造成对象的“越级”

public  和  private结果是不一样的,当属性变为public,this就代表子类,能解释吗

如果父类是Class A,子类是Class B,个人觉得内存结构应该是这样

A = Class A

B = { (继承自Class A) Class B } 
子类对象创建的时候,应该是先创建了父类对象,然后父类的内存块作为子类内存块的一部分(子类=父类内存结构+子类自有)

所以父类中的定义的this调用的方法要么是 父类的方法,要么是 父类中被子类重写的。

你的子类实例中没有定义run方法,访问的就是父类的公共方法run,此时$this应该已经是指向父类了,所以$this->m()调用的就是父类中未被重写的私有m方法

B = { (继承自Class A) 
比如下面这里例子

<?phpclass pa{    public function a(){        $this->sd();  // $this指向父类,而父类中未定义sd方法,子类的sd方法又是私有的,所以没有输出,子类的sd改成public即可输出。    }}class child extends pa{    public function m(){        $this->a();    }    private function sd(){        echo 'sd';    }}$obj=new child();$obj->m();


没有深入理解过php的内部实现,欢迎指导讨论。

还是那句话:私有的是不可侵犯的

没明白,怎么解释public 和 private结果不同

private 私有的,只能被自己访问。不会被继承和覆盖
public 共有的,可任意访问、继承、覆盖


还是那句话:私有的是不可侵犯的

没明白,怎么解释public 和 private结果不同

因为对于php来说 public 和 private 是2种不同的修饰

也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。


没有找到更详细的解释extends作用机理的文章,以下只是我的猜测

我觉得造成这种问题的原因可能在于,虽然表面上是继承了父类,但是父类实际上是存在的,也就是说,如果通过子类的实例化对象来调用父类中的某个方法,那么实际上它进入到了父类的空间里,那么在父类空间里的$this的作用范围就是父类空间本身,而不能跨越到子类的空间中。

之所以会这么猜想,是因为PHP的变量的引用原理,也就是当一个变量的值,是另一个变量的引用时,并不等同于这两个变量变成了同一个变量,其实本身还是两个变量,并且销毁其中一个的时候,另一个仍然存在。

所以基于此我认为,子类的实例化对象不应该使用父类中的$this来代表子类的对象,这样会造成对象的“越级”

public  和  private结果是不一样的,当属性变为public,this就代表子类,能解释吗

按照上面各位大大的解释,private是不能被覆盖的,而public可以被覆盖,所以你改为public之后,就是父类的方法被子类覆盖了



还是那句话:私有的是不可侵犯的

没明白,怎么解释public 和 private结果不同

因为对于php来说 public 和 private 是2种不同的修饰

也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。

run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢

private 私有的,只能被自己访问。不会被继承和覆盖
public 共有的,可任意访问、继承、覆盖

答非所问



没有找到更详细的解释extends作用机理的文章,以下只是我的猜测

我觉得造成这种问题的原因可能在于,虽然表面上是继承了父类,但是父类实际上是存在的,也就是说,如果通过子类的实例化对象来调用父类中的某个方法,那么实际上它进入到了父类的空间里,那么在父类空间里的$this的作用范围就是父类空间本身,而不能跨越到子类的空间中。

之所以会这么猜想,是因为PHP的变量的引用原理,也就是当一个变量的值,是另一个变量的引用时,并不等同于这两个变量变成了同一个变量,其实本身还是两个变量,并且销毁其中一个的时候,另一个仍然存在。

所以基于此我认为,子类的实例化对象不应该使用父类中的$this来代表子类的对象,这样会造成对象的“越级”

public  和  private结果是不一样的,当属性变为public,this就代表子类,能解释吗

按照上面各位大大的解释,private是不能被覆盖的,而public可以被覆盖,所以你改为public之后,就是父类的方法被子类覆盖了
那与this的指向有什么关系?




还是那句话:私有的是不可侵犯的

没明白,怎么解释public 和 private结果不同

因为对于php来说 public 和 private 是2种不同的修饰

也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。

run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢

run()啥时候是子类方法了,你run是定义在父类里的啊。它的public表示它可以被子类访问和重写,不代表它就直接属于子类的方法啊。

$child->run()执行时$child实例里是没有run方法的。所以按照8楼所说,因为child是子类,所以在子类中找不到时到父类空间中找,这时父类中的run方法中的$this就是表示父类本身。

你使用$this->m()时,由于$this目前表示父类,而m()又是private的,所以不存在被覆盖的可能,子类里定义的是属于子类自己的,跟父类无关。调用的就是父类的m,而不是子类。

当你把父类的m()的private改成public,父类的m()就存在被重写的可能,所以程序会去继承他的子类中去寻找(也就是你的$child),如果找到则调用子类的,没找到调用父类自己的m()

第一种请看等价于:

<?phpclass child{    private function m(){        echo 'Parent\'s function';    }    public function run(){        $this->m();    }    public function m(){        echo 'child\'s function';    }}$obj=new child();$obj->run();


这样搞也可以吗?

搞错了,请无视。竟然不能编辑。。

$this 是类实例化后的对象
所以 $this 指向的是对象,而不是类
实例化后,无论是基类还是继承类的方法都在对象中
具体执行的是哪个方法由 php 根据规则决定

class pa{  private function m(){    echo __METHOD__ . ' Parent\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();  }}class child extends pa{  public function m(){   echo __METHOD__ . ' child\'s function';  }}$obj=new child();$obj->run();
得到 pa pa::m Parent's function
pa::m 方法是私有的,不可被覆盖

class pa{  public function m(){    echo __METHOD__ . ' Parent\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();  }}class child extends pa{  public function m(){   echo __METHOD__ . ' child\'s function';  }}$obj=new child();$obj->run();
得到 pa child::m child's function
pa::m 方法是公有的,可以被覆盖

class pa{  private function m(){    echo __METHOD__ . ' Parent\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();  }}class child extends pa{  public function m(){   echo __METHOD__ . ' child\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();    parent::run();  }}$obj=new child();$obj->run();
得到
child child::m child's function
pa pa::m Parent's function

不能理解就慢慢理解吧。规矩不会因为你而改变
我就偏要再“答非所问”一回!

还是那句话:私有的是不可侵犯的
好精辟啊 





还是那句话:私有的是不可侵犯的

没明白,怎么解释public 和 private结果不同

因为对于php来说 public 和 private 是2种不同的修饰

也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。

run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢

run()啥时候是子类方法了,你run是定义在父类里的啊。它的public表示它可以被子类访问和重写,不代表它就直接属于子类的方法啊。

$child->run()执行时$child实例里是没有run方法的。所以按照8楼所说,因为child是子类,所以在子类中找不到时到父类空间中找,这时父类中的run方法中的$this就是表示父类本身。

你使用$this->m()时,由于$this目前表示父类,而m()又是private的,所以不存在被覆盖的可能,子类里定义的是属于子类自己的,跟父类无关。调用的就是父类的m,而不是子类。

当你把父类的m()的private改成public,父类的m()就存在被重写的可能,所以程序会去继承他的子类中去寻找(也就是你的$child),如果找到则调用子类的,没找到调用父类自己的m()

这时父类中的run方法中的$this就是表示父类本身。按这么说,你的理论就是,实力化子类的时候,父类也实例化了?this只能引用对象不能引用类,你的意思是创建子类的时候,顺便把父类实例化了?否则this这个东西就是个矛盾,都不存在父类对象,哪存在this

$this 是实例化后的对象
就像 $obj=new child(); 后的 $obj 一样
如果你是在对象内部访问对象的方法和属性的话,总不能老是要把 $obj 传进去吧?
所以就有了 $this 这个载体

其实所有面向对象的语言中都有这个 this,也的确迷糊了众多的初学者。其实没有什么好不理解的
this 就是对象自己

$this 是类实例化后的对象
所以 $this 指向的是对象,而不是类
实例化后,无论是基类还是继承类的方法都在对象中
具体执行的是哪个方法由 php 根据规则决定

class pa{  private function m(){    echo __METHOD__ . ' Parent\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();  }}class child extends pa{  public function m(){   echo __METHOD__ . ' child\'s function';  }}$obj=new child();$obj->run();
得到 pa pa::m Parent's function
pa::m 方法是私有的,不可被覆盖

class pa{  public function m(){    echo __METHOD__ . ' Parent\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();  }}class child extends pa{  public function m(){   echo __METHOD__ . ' child\'s function';  }}$obj=new child();$obj->run();
得到 pa child::m child's function
pa::m 方法是公有的,可以被覆盖

class pa{  private function m(){    echo __METHOD__ . ' Parent\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();  }}class child extends pa{  public function m(){   echo __METHOD__ . ' child\'s function';  }  public function run(){    echo __CLASS__ . ' ';    $this->m();    parent::run();  }}$obj=new child();$obj->run();
得到
child child::m child's function
pa pa::m Parent's function

不能理解就慢慢理解吧。规矩不会因为你而改变
我就偏要再“答非所问”一回!


所以,版主的意思是,子类实例化前,父类也必须先实例化,否则存在在父类中的this没有父类对象供引用,这是第一段代码的结论。
但是根据第二段代码,父类run里面的this调用了子类对象的方法,所以结论,this指向子类,和第一段代码矛盾

this到底指向父类还是子类对象
那么,父类方法中的this,到底引用的是父类,还是子类对象?(难道存在父类对象),根据php代码的运行结果,明显矛盾,一会指向父类一会指向子类

$this 是实例化后的对象
就像 $obj=new child(); 后的 $obj 一样
如果你是在对象内部访问对象的方法和属性的话,总不能老是要把 $obj 传进去吧?
所以就有了 $this 这个载体

其实所有面向对象的语言中都有这个 this,也的确迷糊了众多的初学者。其实没有什么好不理解的
this 就是对象自己

你说的这个我明白,我真正不明白的地方是,子类继承父类方法function a()(这个方法a()内用到了this),这个继承过来的this,到底是谁的this?13楼的回答看得出来他明白了我是什么意思,但是解释的有矛盾,而版主还是没理解我的意思,我不是不明白private和this的规则,我市不知道在继承过程中,this传到了子类的过程中,指向发生了改变还是怎么回事,你的前2个代码的运行结果,明显是php运行机制中的矛盾点

没有什么子类对象和分类对象
也不存在“子类实例化前,父类也必须先实例化”
实例化的只是一个类
只不过这个类可能包还有继承过来的方法和属性

再重复一遍:this 就是对象自己

既然这样,那么继承过来的子类应该等同于下面把

class child extends pa{    public function m(){        echo 'child\'s function';    }	public function run(){//只继承了run(),m()私有,没继承        $this->m();    }}

那么this就是指向这个类(child)的对象,可是他用了一个不存在的m()方法




还是那句话:私有的是不可侵犯的

没明白,怎么解释public 和 private结果不同

因为对于php来说 public 和 private 是2种不同的修饰

也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。

run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢


最后回复一帖,不想在这个问题多做纠结了

首先,看下面这个例子

<?phpclass pa{    private function m(){        echo 'Parent\'s function';    }}class child extends pa{    public function run(){        if(is_callable($this, 'm')) {			echo 'private function can callable';		} else {			echo 'private function can not callable';		}    }}$obj=new child();if(method_exists($obj, 'm')) {	echo 'private function can extends';} else {	echo 'private function can not extends';}$obj->run();


接着再看
<?phpfunction print_method($obj) {	$refObj = new ReflectionObject($obj);	foreach($refObj->getMethods() as $refFun) {		echo "Define class name : ", $refFun->getDeclaringClass()->getName(), "\n";		echo "Modifiers for method ", $refFun->name,":\n";		echo $refFun->getModifiers() . "\n";		echo implode(' ', Reflection::getModifierNames($refFun->getModifiers())) . "\n";	}} class pa{    private function m(){        echo 'Parent\'s function';    }    public function run(){        print_method($this);		// 从上面的输出可以看到,$this = $obj,		// 这里隐含一个输出,为什么会隐藏,这就是继承的关系,我们知道public和protected会被子类同名给覆盖		// 但是private又会被保护,不能覆盖,那么其实就是有2份m,一个private m,另外一个就是子类 public m		$this->m();		// 而这里的m调用时,会找那个m调用呢?		// 很简单,就是优先找当前method所定义class处的private,因为有了private就不用考虑继承覆盖的问题		    }	protected}class child extends pa{    public function m(){        echo 'child\'s function';    }}$obj=new child();print_method($obj);$obj->run();


但愿你能明白。

貌似要你那么做需要延迟静态绑定

私有的无论是不是父类都不能调用

$this 是实例化后的对象
就像 $obj=new child(); 后的 $obj 一样
如果你是在对象内部访问对象的方法和属性的话,总不能老是要把 $obj 传进去吧?
所以就有了 $this 这个载体

其实所有面向对象的语言中都有这个 this,也的确迷糊了众多的初学者。其实没有什么好不理解的
this 就是对象自己
应该是他本身吧!无论这个他是父类或子类、或者别的类?

?爆了~~~ 留名学习中~

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn