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

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

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

以前咱们讲过静态调用绑定(late static binding),nice,如今来考考你呗~ :smirk:bash

<?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>';
?>
复制代码

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

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

咱们知道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:ui

...
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:this

pilishen.com
pilishen.com

laravel
laravel
laravel
复制代码

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

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

<?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:

相关文章
相关标签/搜索