Fork me on Baidu

static 和 self 区别

1,在 PHP 中,我们可以使用 new static() 结合私有构造函数和一个静态方法来实现单例模式。以下是一个简单的例子

class Singleton {
    // 私有化构造函数,防止外部直接实例化
    private function __construct() {}

    // 静态变量用于存储单一实例
    private static $instance;

    // 使用 new static() 创建并返回单例对象的公共静态方法
    public static function getInstance(): self {
        if (null === static::$instance) {
            static::$instance = new static();
        }
        return static::$instance;
    }

    // 防止克隆
    private function __clone() {}

    // 示例:类中的一个简单方法
    public function doSomething() {
        echo 'Singleton is working.';
    }
}

// 获取 Singleton 类的单例对象
$singleton1 = Singleton::getInstance();
$singleton1->doSomething();

// 再次获取同一个实例
$singleton2 = Singleton::getInstance();
// 因为是单例,所以 $singleton1 和 $singleton2 实际上指向的是同一对象

在这个例子中,getInstance() 方法使用 new static() 来创建并返回类的唯一实例。由于构造函数是私有的,因此无法通过其他方式实例化这个类。这样就确保了在整个应用程序中,无论何时调用 getInstance() 方法,都只会返回同一个实例,从而实现了单例模式。

在 PHP 中,new static() 和 new self() 都是用来创建对象的表达式,但它们之间存在一定的区别: 
1. new self(): - self 关键字指向当前类,无论是在哪个类中调用,它始终指向定义该方法的类。 - 当你在某个类的方法中使用 new self() 时,它会创建该类的一个新实例。
2. new static(): - static 关键字指向的是实际运行时的类,也就是说,在继承层次结构中,如果子类重写了父类的方法并在这个方法内部使用 new static(),那么它将创建
的是当前上下文中的类(即子类)的实例,而不是父类的实例。 - 这种动态绑定的行为使得 new static() 在处理继承关系时更加灵活,特别是在工厂方法、单例模式或者构造函数等需要创建当前类实例的场景下非常有用。
总结一下:
- 如果你希望总是创建当前类的新实例,而不考虑继承和覆盖的情况,使用 new self()。
- 如果你希望根据实际调用类来创建相应类的新实例(即支持多态性),尤其是在面向对象设计中处理继承关系时,应使用 new static()。

 

<?php

class Father {
    // 父类中的 say 方法
    public function say() {
        return 'PHP';
    }

    // 父类中的静态 demo 方法
    public static function demo() {
        $obj = new static();

        // 猜想一下,应该调用哪个 say 方法呢?
        return $obj->say();
    }
}

class Sub extends Father {
    // 子类中的 say 方法
    public function say() {
        return 'ThinkPHP5';
    }
}

// 调用父类的静态 demo 方法
echo Father::demo();  // 返回: PHP

// 调用子类的静态 demo 方法,实际会调用子类重写的 say 方法
echo Sub::demo();  // 返回: ThinkPHP5
在上述代码中,Father::demo() 和 Sub::demo() 都是调用静态方法。
在 demo 方法内部使用了 new static() 创建对象,
由于 static 关键字指向调用该静态方法的类,
因此: - 当调用 Father::demo() 时,new static() 实际创建的是 Father 类的对象,
所以调用的是父类的 say 方法。 - 当调用 Sub::demo() 时,new static() 实际创建的是 Sub 类的对象,所以调用的是子类重写的 say 方法
posted @ 2024-01-23 20:11  consideration  阅读(10)  评论(0编辑  收藏  举报