程序员PHP经验分享

php 不符合常理的static self parent

2018-01-10  本文已影响54人  宋大肿

没有废话 ,我想直接抛出问题。

一、php继承问题

上代码。


class father{
    public function __construct(){
      echo "类father";
}
}
class child extends father{
    public function __construct(){
      echo "类child";
}
}

$p=new child();

输出结果: 类child

如果我们接触过纯面向对象的语言 :c#/java;
按照他们的语法,以上例子将会输出 :
类father
类child

当我们在new子类对象的时候,编译器应该会实例化它的父类,以此来产生一个继承链条,我们看到表面上php仅仅实例化了一个子类对象,这并不科学,也是后续问题产生的一个根本原因:php到底存不存在继承链?

二、static 、self、parent这些关键字

class father{
public $a="father";
public function __construct(){
      echo "类father";
}
public function Say(){
      echo __CLASS__."say";
}
}
class child{
    public function __construct(){
        parent::construct();
    self::Say();
static::Say();  

$this->a;
      echo "类 child";
}
}
$childs=new child();

如果php不存在继承链,那么以上程序将报错。
所以php是存在继承链。

并且以上存在一些语法规则,子类可以通过self或者是static等关键字,去调用父类中可供调用的方法,和$this类似。

那么我们是不是就可以理解成:self::或者是static::语法,指向了一个father类的实力对象? 要不然成员方法怎么调用?

但是奇怪的是:static::/self:: 不能调用属性字段(非静态),parent::也是如此。

这个就尴尬了,凭什么非静态的方法能调用,字段属性就不行?

那么应该推翻self::/static::是对象的引用,他们应该是类层面上的引用。

产生了矛盾。

凭什么能调用成员的方法,却无法调用成员属性?

答案存在于内存分布上面:
我们知道内存分为4部分:

  1. 静态数据区
  2. 代码区
    实例化对象的时候,将属性都存放到了堆里面。方法存在于代码区,调用的时候,根据类指针来寻找存放地址,进行调用。

我们可以大体了解到,属性可以在代码运行时动态改变值。方法,一旦我们定义好之后,代码编译完成方法体就很难改变,所以在内存中如此存放,更加节约空间。

所以,不管是static 还是self、parent都是指向类指针,可以调用静态变量,以及方法列表。
$this真正指向本对象。

上一篇 下一篇

猜你喜欢

热点阅读