>백엔드 개발 >PHP 튜토리얼 >this 在继承的类中指向父类?

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

WBOY
WBOY원래의
2016-06-23 14:19:021257검색

<?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 就是对象自己
应该是他本身吧!无论这个他是父类或子类、或者别的类?

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

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.