php $this到底是什么

一般说法:¥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  extends  a{
     public  $var  'var b ' ;
     public  function  m(){
         echo  'fun b ' ;
     }
}
$li  new  b();
$li ->run();
echo  '<hr>' ;
var_dump( $li );

输出:

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();
         var_dump( $this );
         echo  '' ;
     }
}
 
class  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  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有些“奇怪”的现象。
提问者评价
谢谢理解多了
评论(1)   |   7   0

cmoooo   | 来自团队:其他编程语言 | 十级 采纳率73%

按默认排序 | 按时间排序

其他2条回答

2013-06-11 21:18 只牵佑手   |   五级
首先,你new的是b类,那你就可以表用b类里的所有方法,而b类继承了a类,那就是相当于b类拥有a类的全部方法,所以你当然是可以访问run函数的,而run函数是调用的$this本类的m方法,你之前实例化的是b类,b类重写了m方法,那当然是输出b类的m方法的结果。当改为private时,成为私有的,私有的是不可以被继承的,所以b类的m方法也不能算是重写a类的m方法,应该算是两个方法只是名字相同罢了,那第二次$this->m()自然是输出a类的m方法结果了(第二次m没有被重写,只能输出a类的结果)。纯属个人的看法
追问:
第二次输出的是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方法了??那如果有其它子类也继承这个父类,并且没有重写这个父类的方法的话那如何解释了??


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值