一般说法:¥this表示当前所在类对象这个很不明确
$this取决于¥this所在方法被调用时的执行对象(环境)
方法执行环境:当前方法在哪个对象环境下执行,该方法的¥this就表示该对象,针对还原一层层到最初始的方法的对象
举例
<?php
class A{
private function m(){
echo 'aa';
}
public function run(){
var_dump($this);
}
}
$ai = new A();
$ai->run();
echo "<br/>=======<br/>";
class B{
public function m(){
var_dump($this);
echo '<br/><br/>';
A::run();
}
}
$li = new B();
$li->m();
?>
但是如果是继承过来的另算,此run方法来自继承,所以如果找属性话可以算做this是a类的,又因为是私有方法,所以不用考虑b类是否继承该方法,所以输出是aa
<?php
class a{
private function m(){
echo 'aa';
}
public function run(){
$this->m();
}
}
class b extends a{
public function m(){
echo 'bb';
}
}
$li = new b();
$li->run();
?>
class a{ public function m(){ echo 'aa'; } public function run(){ $this->m(); } } class b extends a{ public function m(){ echo 'bb'; } } $li = new b(); $li->run(); 谁能跟我分析一下这为什么是访问的b类里面的m方法,如果把a类的m方法权限改为private,又为什么变成访问的是a类的m方法了。。 声明一个类的时候,如果这个类继承某个类,那么这父类的方法在子类中是如何体现的,完全复制一份吗?
分两步考虑继承的,虽然是b,但是如果调用继承的方法 那么基类中的this实际上还是先考虑a的方法或者属性,然后再考虑子类
如果调用 的是基类私有的那就用私有不能再继承,如果是公有的考虑子类是否继承过从而使用重写的方法
我来说一说:
【一】…………public(仅有)属性和方法的继承…………
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class
a{
public
$var
=
'var a '
;
public
function
m(){
echo
'fun a '
;
}
public
function
run(){
echo
$this
->
var
;
$this
->m();
}
}
class
b
extends
a{
public
$var
=
'var b '
;
public
function
m(){
echo
'fun b '
;
}
}
$li
=
new
b();
$li
->run();
echo
'<hr>'
;
|
输出:
1
2
3
4
5
|
var b
fun b
————————————————————————————
object(b)[1]
public 'var' => string 'var b ' (length=11)
|
在这段代码中所表示的,是我们常见的一种继承方式,同为公有属性的$var 和公有方法m()
在这里,$var和m()都被继承并覆写,实例化过后,内存中只有一个$var实例,通过var_dump($li);我们可以看到它。
【二】…………private(私有)属性和方法的继承…………
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class
a{
private
$var
=
'var a '
;
private
function
m(){
echo
'fun a '
;
}
public
function
run(){
echo
$this
->
var
;
$this
->m();
echo
''
;
}
}
class
b
extends
a{
private
$var
=
'var b '
;
private
function
m(){
echo
'fun b '
;
}
public
function
run(){
echo
$this
->
var
;
$this
->m();
var_dump(
$this
);
echo
''
;
parent::run();
}
}
$li
=
new
b();
$li
->run();
echo
'<hr>'
;
var_dump(
$li
);
|
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var b
fun b
object(b)[1]
private 'var' => string 'var b ' (length=11)
private 'var' (a) => string 'var a ' (length=11)
.
.
var a
fun a
object(b)[1]
private 'var' => string 'var b ' (length=11)
private 'var' (a) => string 'var a ' (length=11)
.
————————————————————————————————
object(b)[1]
private 'var' => string 'var b ' (length=11)
private 'var' (a) => string 'var a ' (length=11)
|
这个时候,我们可以看到,在调用run方法时,首先它会调用到b类的私有属性$var 和私有方法m(),随后,又使用parent::run()调用父类的run()方法,我们可以看到,父类的run()方法调用后,它所调用的属性和方法,都是a类的两个私有属性和方法,这种形式,和你的问题一致;
而它与$this指向无关,我们可以在这里看到,两个$this都是指向b类。
而最有意思的是,在$li句柄中,我们却看到了两个属性!一个是b类的属性,一个是a类的属性,这两个属性同时存在着,那么,私有方法也自然是同时存在着。
【三】…………私有属性和方法能不能被继承…………
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class
a{
private
$var
=
'var a '
;
private
function
m(){
echo
'fun a '
;
}
}
class
b
extends
a{
public
function
run(){
echo
$this
->
var
;
$this
->m();
}
}
$li
=
new
b();
$li
->run();
|
输出:
1
2
|
Notice: Undefined property: b::$var in E: ... on Line 9
Fatal error: Call to private method a::m() from context 'b' in E: ... on Line 10
|
这可以证明,私有属性和方法,无法被继承,所以,你的代码示例中所说,将a类的m()方法更改为private后,会显示aa的属性,也就可以理解明白了。
将a类的m()方法更改为private后,会显示aa的属性 还是无法理解,虽然没有继承过去,但其子类b也是调动个m方法,而它与$this指向无关,我们可以在这里看到,两个$this都是指向b类。你这里说这this指向的是b。那应该还是调用b类的m方法才对的啊
“将a类的m()方法更改为private后,会显示aa的属性”这句话是我打字太顺了手,出了差错,没有最后“的属性”三字,是:“将a类的m()方法更改为private后,会显示aa” 它确实是与$this的指向无关的,但却与$this的位置有关系。 私有的属性和方法,只能够在该类中被调用,像你的这个程序中,没有属性,只有方法,而run()方法虽然被继承到了b类中,但它仍然属于a类的方法,并不是b类的,所以,它里面的$this->m()自然就是a类中私有的方法m(),而非b类中“新定义”的公有方法m(),这就是说,内存中实际上是有两个m()方法的,一个属于a类,一个属于b类,两个毫不相关,各是各的。 当你调用继承自a类的方法run()时,run()方法中的$this,这个$this位于a类之中,隶属于a类,所以a类中的私有方法m()是对其开放的,然后我们再看,如果这个$this出现在b类中,那这个时候,这个b类中的$this->m(),指向的就不再是a类的私有方法m()了,而是b类中“新定义的”的m()。 为什么说是“新定义”?因为a类中的m()方法是私有的,无法继承嘛,所以b类的m()方法是“新定义”的。 这里面有一个弯,你反过来再想想,对于a类来说,a类里的run()函数是不是属于a类的?是吧? 那么,在run()方法中使用$this,还无法访问它里面的私有属性,却是跑到其它地方去访问一个“新定义”的一个新方法,这才叫奇怪不是? 所以,这个现象是正常的,而我们却是以“为什么我把public改为private,它就变了呢?”这个先入为主的思想给误导了。 不知道你有没有理解?
(内存中实际上是有两个m()方法的,一个属于a类,一个属于b类)但如果两个都是public在内存中也是应该有两个方法才对吧,父类的m方法肯定也还存在,不然就不可以通过parent::来调用这父类的方法了,那我在两个都是public 的情况下,这$this的指向 (它确实是与$this的指向无关的,但却与$this的位置有关系。 )这一句话不适合了是吧??这this就直接指向了子类的m方法了
嗯,你有些较真了。 你想想,继承是做什么的?继承的一个大的特性就是可以把继承过来的“公有的”属性和方法,以及“受保护的”属性和方法继承到子类中去? 既然这种public,和protected的属性和方法都已经被顺位继承了,那么它还属于原来的a类了吗?不属于了吧?(其实这里我的用语并不准确,它原本的类还是属于原本的,但是因为这些公有的和受保护的属性和方法所拥有的特性,必须要将它的“$this关联”给赋予到子类中去才有意义,这个意义才是主要的,它就像我们写一个复杂的代码,里面可能会出现标志位,这个标志位表示了程序中某个意义的特性,然后我们可以根据这个特性,来判断它最终的结果,这个$this关联,就是如此) 然后这个被更改了$this关联的属性和方法,再被你重写或者叫覆写了,那这个在a类中的$this->m()【注意这里不是$this,而是$this->m()】,还会去指向自己类里的对应方法? 如果是这样的话,那PHP的开发团队都可以解散了。 呵呵,开个玩笑。 其实就是这么个道理,不知道你现在还有疑问没有。 —————— 另外再补充一点,就是关于parent::, parent,这个关键字是PHP里面一个很重要的存在,它的作用就是能够在你需要的时候调取到父类中的相关属性和方法,它的存在比较特殊,它就是一个站在子类中去看父类的一个通道口。 这个通道口能够把父类中“公有的”和“受保护”的属性和方法调用出来,而不动用自己的或者已经被重写的属性和方法,却动不了父类中私有的属性和方法,因为父类中私有的已经决定了它绝对不允许被子类所使用,它只针对本类,而这个私有的特性,也造成了这个$this有些“奇怪”的现象。
-
提问者评价
-
谢谢理解多了
第二次输出的是a类的方法那,是不是说明 这$this->m();这里的this指向的是a类,不是指向b这个子类,那为什么第一次的this指向的是b这个子类呢??方法被重写了,那不代表父类的这个方法不存在了吧?要访问父类的方法还是可以访问的。
public时,实例化b类,方法m被重写,那么内存中应该是只有一个方法m,而不会有两个m方法,所以只会输出b类里m方法的结果。这个可以明白吧。 而第二次private时,内存中就两个m函数,那自然就是访问自己的私有属性m函数了,即a类的m方法
public时,实例化b类,方法m被重写,那么内存中应该是只有一个方法m,而不会有两个m方法??我的理解是两个m方法啊?如果是只有一个的话那表示父类没有这个m方法了??那如果有其它子类也继承这个父类,并且没有重写这个父类的方法的话那如何解释了??