Fork me on GitHub

PHP静态属性的继承问题


和你们这些少爷不同,我们光是活着就竭尽全力了。

非静态属性

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
31
32
33
34
35
36
37
38
<?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('baidu.com');
echo $bar->getInstance(); // baidu.com
echo (new Foo)->getInstance(); // NULL
echo "\n";
$baz = new Baz;
$baz->setInstance('laravel');
echo $baz->getInstance(); // laravel
echo $bar->getInstance(); // baidu.com
echo (new Foo)->getInstance(); // NULL

说明:
非静态属性的继承关系子类会继承父类的属性和方法,子类中的修改并不会影响到父类中属性的改变

静态属性

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
<?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('baidu.com');
echo Bar::getInstance(); // baidu.com
echo Foo::getInstance(); // baidu.com

说明:
子类对属性的修改已经影响到了父类, 当然,这是在子类没有设置相同属性的情况下, 此时如果子类设置了相同的静态属性, 则如果对子类中这个属性的修改, 并不会影响到父类

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
<?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 {
protected static $instance;
}
Bar::setInstance('baidu.com');
echo Bar::getInstance(); // baidu.com
echo Foo::getInstance();

再看一个子类之间相互影响的例子

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
31
32
33
34
35
<?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 {
}
class Baz extends Foo {
}
Bar::setInstance('baidu.com');
echo Bar::getInstance(); // baidu.com
echo Foo::getInstance(); // baidu.com
echo "\n";
Baz::setInstance('laravel');
echo Baz::getInstance(); // laravel
echo Bar::getInstance(); // laravel
echo Foo::getInstance(); // laravel

修改其中一个子类, 父类以及该父类的其他子类都会受到影响

laravel 源码分析

在Laravel 中的 app()这个辅助函数可以获得 一个 Application 对象实例

1
2
3
4
5
6
7
8
function app($abstract = null, array $parameters = [])
{
if (is_null($abstract)) {
return Container::getInstance();
}
return Container::getInstance()->make($abstract, $parameters);
}

进入这个Container类, 发现仅仅是一个静态属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Container implements ArrayAccess, ContainerContract
{
/**
* The current globally available container (if any).
*
* @var static
*/
protected static $instance;
......
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}

然后我们从入口文件看起
index.php

1
$app = require_once __DIR__.'/../bootstrap/app.php';

app.php

1
2
3
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);

Application这个类, 继承了 Container 类, 而Container这个类中有一个静态属性$instance

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
31
class Application extends Container implements ApplicationContract, HttpKernelInterface
{
......
public function __construct($basePath = null)
{
if ($basePath) {
$this->setBasePath($basePath);
}
$this->registerBaseBindings();
$this->registerBaseServiceProviders();
$this->registerCoreContainerAliases();
}
protected function registerBaseBindings()
{
static::setInstance($this);
$this->instance('app', $this);
$this->instance(Container::class, $this);
$this->instance(PackageManifest::class, new PackageManifest(
new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
));
}

正是是用了静态属性继承这一特性;

http://pilishen.com/posts/Inheritance-with-the-static-elements-in-php-especially-during-late-static-binding