PHP静态属性(static variable)的继承(inheritance),尤其是在静态调用绑定(late static binding)中...

本文来自pilishen.com----原文链接; 欢迎来和pilishen一起学习php&Laravel;学习群:109256050

该篇属于《Laravel底层核心技术实战揭秘》这一课程《laravel底层核心概念解析》这一章的扩展阅读。由于要真正学好laravel底层,有些PHP相关的知识必须得了解,考虑到学员们的基础差异,为了避免视频当中过于详细而连篇累牍,故将一些laravel底层实现相关的PHP知识点以文章形式呈现,供大家预习和随时查阅。

之前我们讲过静态调用绑定(late static binding),nice,现在来考考你呗~ :smirk:

<?php
class Foo {
	protected static $instance;

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

	public static function getInstance()
	{
		return static::$instance;
	}
}
class Bar extends Foo {
	
}

Bar::setInstance('pilishen.com');
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
?>
复制代码

你说两个输出结果分别是啥呢?

echo Bar::getInstance() .'<br>';输出的肯定是pilishen.com,问题是echo Foo::getInstance() .'<br>';.

我们知道static::指向的是实际调用它的class,所以Bar::setInstance('pilishen.com');执行的时候,在setInstance()方法里相当于是Bar::$instance = 'pilishen.com',也即是class Bar的静态属性$instance设置成了pilishen.com,而父类class Foo的静态属性$instance没动着它,所以应该还是空的,对吧?

现实是残酷的: :open_mouth:

pilishen.com
pilishen.com
复制代码

好吧,现实是需要接受的,继续作! :smiling_imp:

...
class Baz extends Foo {
	
}


Bar::setInstance('pilishen.com');
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';

echo '<hr>';
Baz::setInstance('laravel');
echo Baz::getInstance() .'<br>';
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
?>
复制代码

我们又搞了一个class Baz,也是扩展了class Foo,然后Baz::setInstance('laravel');,这个时候很显然Baz$instancelaravel了,问题是BarFoo的呢?我们知道它两个之前都是pilishen.com,再来接受下现实? :scream:

pilishen.com
pilishen.com

laravel
laravel
laravel
复制代码

好吧,牵一发动全身!子类能改变父类?!子类能改变子类?!厉害了哦~ :thumbsup:

为了测试这只是静态属性的问题,也即证明一下我们传统的关于属性继承的思路没错,我们改一下:

<?php
class Foo {
	protected $instance='Null';

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

	public function getInstance()
	{
		return $this->instance;
	}
}
class Bar extends Foo {
	
}
class Baz extends Foo {
	
}

$bar = new Bar;
$bar->setInstance('pilishen.com');
echo $bar->getInstance() .'<br>';
echo (new Foo)->getInstance() .'<br>';

echo '<hr>';
$baz = new Baz;
$baz->setInstance('laravel');
echo $baz->getInstance() .'<br>';
echo $bar->getInstance() .'<br>';
echo (new Foo)->getInstance() .'<br>';
?>
复制代码

现在的现实就是可以接受的了:

pilishen.com
Null

laravel
pilishen.com
Null
复制代码

所以,静态属性的继承跟我们默认想象的不一样哦: :sunglasses:

尽管我们在子类里可以获取它,可以修改它,但是这个它,指向的都是父类里的那个静态属性,确实是子类能改变父类,子类能改变子类。也或者说,所有的父类和子类,都是共享这一个静态属性。

当然,上面的情况仅发生在你的子类里,没有额外定义一个同名静态属性的情况下,如果这样:

<?php
class Foo {
	protected static $instance='null';

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

	public static function getInstance()
	{
		return static::$instance;
	}
}
class Bar extends Foo {
	protected static $instance;
}
class Baz extends Foo {
	protected static $instance;
}


Bar::setInstance('pilishen.com');
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';

echo '<hr>';
Baz::setInstance('laravel');
echo Baz::getInstance() .'<br>';
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
?>
复制代码

这里我们在子类里面都额外定义了一个同名的$instance,这个时候就是各自的是各自的了,就不是共享了:

pilishen.com
null

laravel
pilishen.com
null
复制代码

好了,知道这些个有什么用呢?

laravel里大量使用了静态属性,当然也包括静态调用绑定,那么你在查看源码的时候就要注意这一点喽~父类和子类是共享的一个静态属性吗?还是子类里面有重新定义呢?子类更改静态属性,会影响父类吗? :sleeping:

最简单的,laravel如何保证整个程序,那么多个类,他们在运行的时候都是用的同一个laravel实例本身呢?都是同一个$app呢?现在明白了吧~ :unamused:

不明白也不要紧,回头我们在《Laravel底层核心技术实战揭秘》中一一详解,记得有这么回事就好~ :muscle:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值