美文网首页
PHP静态属性中的子类改变父类、子类改变子类的问题。

PHP静态属性中的子类改变父类、子类改变子类的问题。

作者: houxin | 来源:发表于2020-09-08 15:13 被阅读0次

一、静态实例

这里我定义了一个如下的类

class A{
    protected static $instance;

    public static function setInstance($ins){
        static::$instance = $ins;
    }

    public static function getInstance(){
        return static::$instance;
    }
}
class B extends A
{

}

// 设置值
B::setInstance('hello');

var_dump(B::getInstance()); echo '<br>';
var_dump(A::getInstance()); echo '<br>';

这里static::的作用类似于self::,但是是有区别的 。具体差别请自行查询了解。

你觉的会输出什么?也许你会觉得,第一个输出'hello',第二个应该输出'null'。
但是,实际输出

string(5) "hello"
string(5) "hello"

我们又加一个C类,继承与A类,然后通过C去修改静态变量$instance的值。

...
class C extends A
{

}
C::setInstance('world');
var_dump(C::getInstance()); echo '<br>';
var_dump(B::getInstance()); echo '<br>';
var_dump(A::getInstance()); echo '<br>';

此时再打印,你怎么看?可能又要猜错了。
此时输出的是

string(5) "world"
string(5) "world"
string(5) "world"

此时你是不是已发现,子类改变了父类的值,并改变了和它一起继承的另外的一个子类的值。不知道有没有颠覆你的想象。先提一句,这只是静态属性的问题。具体请往下看。

二、普通实例

这次展示下普通实例下的效果

class A{
    protected $instance;

    public function setInstance($ins){
        $this->instance = $ins;
    }

    public function getInstance(){
        return $this->instance;
    }
}
class B extends A
{

}


class C extends A
{

}
// 设置值
$b = new B;
$b->setInstance('hello');
var_dump($b->getInstance()); echo '<br>';
var_dump((new A)->getInstance()); echo '<br>';

echo '<hr>';

$c = new C;
$c->setInstance('world');
var_dump($c->getInstance()); echo '<br>';
var_dump((new B)->getInstance()); echo '<br>';
var_dump((new A)->getInstance()); echo '<br>';

结果如下

string(5) "hello"
NULL

string(5) "world"
NULL
NULL

这种情况,就比较符合大家的预期。

三、原因分析

所以,静态属性的继承跟我们默认想象的不一样哦,尽管我们在子类里可以获取它,可以修改它,但是这个它,指向的都是父类里的那个静态属性。
确实是子类能改变父类,子类能改变子类。也或者说,所有的父类和子类,都是共享这一个静态属性。
当然,上面的情况仅发生在你的子类里,没有额外定义一个同名静态属性的情况下。
如果这样:

class A{
    protected static $instance;

    public static function setInstance($ins){
        static::$instance = $ins;
    }

    public static function getInstance(){
        return static::$instance;
    }
}
class B extends A
{
    protected static $instance;
}


class C extends A
{
    protected static $instance;
}
// 设置值
B::setInstance('hello');

var_dump(B::getInstance()); echo '<br>';
var_dump(A::getInstance()); echo '<br>';

echo '<hr>';
C::setInstance('world');
var_dump(C::getInstance()); echo '<br>';
var_dump(B::getInstance()); echo '<br>';
var_dump(A::getInstance()); echo '<br>';

此时打印的结果

string(5) "hello"
NULL

string(5) "world"
string(5) "hello"
NULL

我们在各个子类内部,定义了一个$instance属性,这时候就是各自是各自的了,不再共享了。

用处
很多知名的框架,比如laravel里面大量使用了静态属性,当然也包括静态调用绑定,在查看源码的时候就要注意这一点。父类和子类是不是共享的一个静态属性,子类里面有没有重新定义。子类更改静态属性是否会影响父类吗。最简单直接的就是laravel框架的$app,它是如何保证整个程序那么多个类,在运行的时候都是用的同一个larave例本身的,都是指向同一个$app的。

相关文章

  • PHP静态属性中的子类改变父类、子类改变子类的问题。

    一、静态实例 这里我定义了一个如下的类 这里static::的作用类似于self::,但是是有区别的 。具体差别请...

  • Java父子类加载顺序

    加载顺序 先上桌结论: 父类静态属性(成员变量) > 父类静态代码块 > 子类静态属性 > 子类静态代码块 > 父...

  • js 继承

    1.构造继承 核心:在子类的内部调用父类,通过call改变父类中this的指向 等于是复制父类的实例属性给子类 ...

  • 2.类与对象

    子类继承父类,子类继承父类的方法,即子类会自动获得父类的功能 子类从父类继承的方法可以由子类重新定义、改变或延伸 ...

  • JAVA高级(8)—— 零碎知识点

    一、子类对父类属性的覆盖 案例代码 输出结果 子类静态变量父类常量子类静态常量 结论 由于private变量受访问...

  • java 类的代码块加载顺序

    输出结果: 总结:父类静态代码块——子类静态代码块——父类代码块——父类构造——子类代码块——子类构造。类的静态代...

  • 构造函数 非静态代码块 构造函数的执行顺序

    执行结果 父类--静态代码块子类--静态代码块父类--非静态代码块父类--构造函数子类--非静态代码块子类--构造函数

  • 零碎知识点

    new对象时初始化顺序:父类静态代码块->子类静态代码块->普通属性->父类构造代码块->父类构造函数->子类构造...

  • 继承

    继承: 子类必须有父类的公有和私有属性和方法 继承私有属性: 改变子类的this指向 继承公有方法: 直接把父类的...

  • 组合继承,寄生组合继承,class继承

    组合继承 说明:核心是在子类的构造函数中通过 Parent.call(this) 继承父类的属性,然后改变子类的原...

网友评论

      本文标题:PHP静态属性中的子类改变父类、子类改变子类的问题。

      本文链接:https://www.haomeiwen.com/subject/pjefektx.html