目錄
回复讨论(解决方案)
首頁 後端開發 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脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1663
14
CakePHP 教程
1420
52
Laravel 教程
1315
25
PHP教程
1266
29
C# 教程
1239
24
說明PHP中的不同錯誤類型(注意,警告,致命錯誤,解析錯誤)。 說明PHP中的不同錯誤類型(注意,警告,致命錯誤,解析錯誤)。 Apr 08, 2025 am 12:03 AM

PHP中有四種主要錯誤類型:1.Notice:最輕微,不會中斷程序,如訪問未定義變量;2.Warning:比Notice嚴重,不會終止程序,如包含不存在文件;3.FatalError:最嚴重,會終止程序,如調用不存在函數;4.ParseError:語法錯誤,會阻止程序執行,如忘記添加結束標籤。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? 什麼是HTTP請求方法(獲取,發布,放置,刪除等),何時應該使用? Apr 09, 2025 am 12:09 AM

HTTP請求方法包括GET、POST、PUT和DELETE,分別用於獲取、提交、更新和刪除資源。 1.GET方法用於獲取資源,適用於讀取操作。 2.POST方法用於提交數據,常用於創建新資源。 3.PUT方法用於更新資源,適用於完整更新。 4.DELETE方法用於刪除資源,適用於刪除操作。

解釋self ::,parent ::和static :: in php oop中的區別。 解釋self ::,parent ::和static :: in php oop中的區別。 Apr 09, 2025 am 12:04 AM

在PHPOOP中,self::引用當前類,parent::引用父類,static::用於晚靜態綁定。 1.self::用於靜態方法和常量調用,但不支持晚靜態綁定。 2.parent::用於子類調用父類方法,無法訪問私有方法。 3.static::支持晚靜態綁定,適用於繼承和多態,但可能影響代碼可讀性。

PHP如何安全地上載文件? PHP如何安全地上載文件? Apr 10, 2025 am 09:37 AM

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

See all articles