<?php
class Test
{
public function getAge()
{
static::getName();
}
}
class Person extends Test
{
protected function getName()
{
echo 'person';
}
}
$person = new Person();
$person->getAge(); // person
被调用的函数 getName 的修饰符可以是 public 或者 protected,但是不能使用 private
大家要明白类与对象的区别。实例化后才是对象。static 是针对的当前的类。$person->getAge();
中,static
就是指的 Person
类
<?php
class ParentClass
{
protected static $instance;
public function __construct()
{
echo 'construct';
echo '<br>';
}
public static function getInstance()
{
if (self::$instance) {
return self::$instance;
}
return self::$instance = new static();
}
public function getName()
{
echo ('ParentClass');
echo '<br>';
}
}
class ChildClass extends ParentClass
{
public function getAge()
{
echo 'age';
echo '<br>';
}
public function getName()
{
echo ('ChildClass');
echo '<br>';
}
}
ChildClass::getInstance()->getName();
ChildClass::getInstance()->getName();
ChildClass::getInstance()->getName();

但是还要注意一种现象
<?php
class ParentClass
{
protected static $instance;
public function __construct()
{
echo 'construct';
echo '<br>';
}
public static function getInstance()
{
if (self::$instance) {
return self::$instance;
}
return self::$instance = new static();
}
public function getName()
{
echo ('ParentClass');
echo '<br>';
}
}
class ChildClass extends ParentClass
{
public function getName()
{
echo ('ChildClass1');
echo '<br>';
}
}
class ChildClass2 extends ParentClass
{
public function getName()
{
echo ('ChildClass2');
echo '<br>';
}
}
ChildClass::getInstance()->getName();
ChildClass::getInstance()->getName();
ChildClass2::getInstance()->getName();
ChildClass2::getInstance()->getName();

如果将父类做个调整
class ParentClass
{
public function __construct()
{
echo 'construct';
echo '<br>';
}
public static function getInstance()
{
static $instance;
if ($instance){
return $instance;
}
return $instance = new static();
}
public function getName()
{
echo('ParentClass');
echo '<br>';
}
}
或者
protected static $instance;
public static function getInstance()
{
if (self::$instance instanceof static){
return self::$instance;
}
return self::$instance = new static();
}
或者
if (self::$instance instanceof static) {
return self::$instance;
}
return self::$instance = new static();
类型运算符
instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例:

这是因为 public static function getInstance()
针对的是当前的类,哪个类使用,就是谁。
new static();
也是针对的当前类
public static function getInstance()
{
static $instance;
if ($instance){
return $instance;
}
return $instance = new static();
}
static $instance; 作用域当前类中的 getInstance 方法
而 protected static $instance; 的作用域是谁继承谁都可以读取这个方法。当 ChildClass 读取后,赋值了,ChildClass2 也可以赋值
但实际中我们会发现上面的方案并不能帮助我们解决问题,如果A类 getInstance() 之后,另一个类B,再使用 getInstance() 方法,A如果再次调用,发现又会重新实例化一次。而,首次实例化之后赋值的数据又会清空,又相当于是首次实例化。只有A getInstance() 之后,后面没有其他类使用此方法,这个实例化才会是单利.
<?php
class Base
{
private static $instance;
/**
* 获取当前类
* @return static
*/
public static function getInstance()
{
if (self::$instance instanceof static) {
return self::$instance;
}
echo '1' . '<br>';
echo '<br>';
return self::$instance = new static();
}
public static function getIn()
{
var_dump(self::$instance);
}
}
class A extends Base
{
public function get()
{
echo 'a' . '<br>';
}
}
class B extends Base
{
public function get()
{
echo 'b' . '<br>';
}
}
A::getInstance()->get();
B::getInstance()->get();
Base::getIn();
B::getInstance()->get();
A::getInstance()->get();
B::getInstance()->get();
A::getInstance()->get();

- 解决方案就是将 $instance 做成一个数组,当前类如果已经实例化过了,则直接返回上次示例话的数据
/**
* 获取当前类
* @return static
*/
public static function getInstance()
{
if (isset(self::$instance[get_called_class()]) && self::$instance[get_called_class()] instanceof static) {
return self::$instance[get_called_class()];
}
echo '1' . '<br>';
var_dump(get_called_class());
echo '<br>';
return self::$instance[get_called_class()] = new static();
}

特别函数
get_called_class() 是系统自带函数,得到的是子类的类名,(此DEMO表示A,B)
get_class(); 得到的是当前类,此demo 得到的是 Base
网友评论