本文来自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
的$instance
是laravel
了,问题是Bar
和Foo
的呢?我们知道它两个之前都是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: