目录
回复讨论(解决方案)
首页 后端开发 php教程 this 在继承的类中指向父类?

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

Jun 23, 2016 pm 02:19 PM

<?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

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

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

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

B = { (继承自Class A) <-- $this Class B }

比如下面这里例子

<?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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在Laravel中使用Flash会话数据 在Laravel中使用Flash会话数据 Mar 12, 2025 pm 05:08 PM

Laravel使用其直观的闪存方法简化了处理临时会话数据。这非常适合在您的应用程序中显示简短的消息,警报或通知。 默认情况下,数据仅针对后续请求: $请求 -

php中的卷曲:如何在REST API中使用PHP卷曲扩展 php中的卷曲:如何在REST API中使用PHP卷曲扩展 Mar 14, 2025 am 11:42 AM

PHP客户端URL(curl)扩展是开发人员的强大工具,可以与远程服务器和REST API无缝交互。通过利用Libcurl(备受尊敬的多协议文件传输库),PHP curl促进了有效的执行

简化的HTTP响应在Laravel测试中模拟了 简化的HTTP响应在Laravel测试中模拟了 Mar 12, 2025 pm 05:09 PM

Laravel 提供简洁的 HTTP 响应模拟语法,简化了 HTTP 交互测试。这种方法显着减少了代码冗余,同时使您的测试模拟更直观。 基本实现提供了多种响应类型快捷方式: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

在Codecanyon上的12个最佳PHP聊天脚本 在Codecanyon上的12个最佳PHP聊天脚本 Mar 13, 2025 pm 12:08 PM

您是否想为客户最紧迫的问题提供实时的即时解决方案? 实时聊天使您可以与客户进行实时对话,并立即解决他们的问题。它允许您为您的自定义提供更快的服务

解释PHP中晚期静态结合的概念。 解释PHP中晚期静态结合的概念。 Mar 21, 2025 pm 01:33 PM

文章讨论了PHP 5.3中引入的PHP中的晚期静态结合(LSB),从而允许静态方法的运行时分辨率调用以获得更灵活的继承。 LSB的实用应用和潜在的触摸

PHP记录:PHP日志分析的最佳实践 PHP记录:PHP日志分析的最佳实践 Mar 10, 2025 pm 02:32 PM

PHP日志记录对于监视和调试Web应用程序以及捕获关键事件,错误和运行时行为至关重要。它为系统性能提供了宝贵的见解,有助于识别问题并支持更快的故障排除

如何注册和使用Laravel服务提供商 如何注册和使用Laravel服务提供商 Mar 07, 2025 am 01:18 AM

Laravel的服务容器和服务提供商是其架构的基础。 本文探讨了服务容器,详细信息服务提供商创建,注册,并通过示例演示了实际用法。 我们将从OVE开始

自定义/扩展框架:如何添加自定义功能。 自定义/扩展框架:如何添加自定义功能。 Mar 28, 2025 pm 05:12 PM

本文讨论了将自定义功能添加到框架上,专注于理解体系结构,识别扩展点以及集成和调试的最佳实践。

See all articles