对于大多数 PHPer 来说,self 与 static 两个 PHP 关键词都不算陌生。我们学会通过 self::xxxx 这种方式来调用当前类的静态属性和方法。而 static 呢?想必很多人只知道它是用于定义一个静态方法和类属性关键词。

这也是我之前的认知。

现在我们来回顾一下这两个关键词的一些常见用法:

// self 用法 1 :调用静态成员属性
<?php
class Person
{
    protected static $maxAddressCount = 5; // 收获地址创建最大数量。

    public function test()
    {
        echo self::$maxAddressCount;
    }
}

$person = new Person();
$person->test();
// self 用法 2 :调用静态方法
<?php
class Person
{
    protected static $maxAddressCount = 5; // 收获地址创建最大数量。

    protected static function getMaxAddressCount()
    {
        return self::$maxAddressCount;
    }

    public function test()
    {
        echo self::getMaxAddressCount();
    }
}

$person = new Person();
$person->test();
// self 用法 3 :创建一个当前对象
<?php
// 单例示例
class Person
{
    private static $instance = null;

    private function __construct() {}

    final public static function getInstance() 
    {
        if (self::$instance == null) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    public function test()
    {
        echo "hello world!";
    }
}

$person = Person::getInstance();
$person->test();

关于 static 关键词的常见用法也在上面 3 个示例中得到综合体现。

我深信上面的用法,任何一个入门的 PHPer 都是非常熟悉的。现在我要讲的是以下两种方式:

new self() 与 new static() 的区别?

我相信很多人都知道 new self() 创建一个当前类的对象,并不知道 new static() 也能创建一个当前类的对象。

关于 new static() 这种用法呢,在官方文档有说明。

PHP 官方把这种方式称为:后期静态绑定。

官方示例 1:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who();
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();

因为 Class B 继承了 Class A。 A 与 B 都有一个静态方法 who()。此时通过 B::test() 的时候,调用的实际上是 Class A 的 who() 方法。

因为子类 Class B 的静态方法 who() 属于在 Class A 之后的子类里面才定义的。而 PHP 的默认特性只允许调用最先定义的。

就这引出了后期静态绑定的概念。

官方示例 2:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // 后期静态绑定从这里开始
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();

我们把 Class A 里面的 test() 方法体的 self 更改为 static 之后,static 代表的永远是指向调用类。也就是说虽然在 Class A 父类里面定义的方法与子类有同名冲突的情况。但是,当子类调用的时候,那么自动切换到子类的静态同名方法。取决于调用者。

大家可以通过运行以上两个示例进行理解。

之所以会有本篇小节内容。是因为我在实际运行当中要继承单例方法导致了这个问题。所以,才牵扯出这个特性。

相关评论(0)
您是不是忘了说点什么?

友情提示:垃圾评论一律封号...

还没有评论,快来抢沙发吧!