这个自我和静态加上单例

使用 $this 来引用当前对象。使用 self 来引用当前的类。换句话说,将 $this->member 用于非静态成员,将 self::$member 用于静态成员。

在下面的例子中,sayHello()sayGoodbye() 正在使用 self$this 差异可以在这里观察到。

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

static 指的是你调用方法的层次结构中的任何类。它允许在继承类时更好地重用静态类属性。

请考虑以下代码:

class Car {
    protected static $brand = 'unknown';
    
    public static function brand() {
         return self::$brand."\n";
    }
}

class Mercedes extends Car {
    protected static $brand = 'Mercedes';
}

class BMW extends Car {
    protected static $brand = 'BMW';
}

echo (new Car)->brand();
echo (new BMW)->brand();
echo (new Mercedes)->brand();

这不会产生你想要的结果:

未知的
未知
未知

这是因为 self 只要调用方法 brand() 就会引用 Car 类。

要引用正确的类,你需要使用 static 代替:

class Car {
    protected static $brand = 'unknown';
    
    public static function brand() {
         return static::$brand."\n";
    }
}

class Mercedes extends Car {
    protected static $brand = 'Mercedes';
}

class BMW extends Car {
    protected static $brand = 'BMW';
}

echo (new Car)->brand();
echo (new BMW)->brand();
echo (new Mercedes)->brand();

这确实产生了所需的输出:

未知的
宝马
梅赛德斯

另请参见 Late static binding

单例

如果你创建的对象很昂贵,或者表示要重用的某个外部资源的连接,即没有连接池的数据库连接或其他系统的套接字,则可以使用 staticself 关键字。使它成为单例的类。关于是否应该使用单例模式有强烈的意见,但它确实有其用途。

class Singleton {
    private static $instance = null;

    public static function getInstance(){
        if(!isset(self::$instance)){
            self::$instance = new self();
        }
        
        return self::$instance;
    }
    
    private function __construct() {
        // Do constructor stuff
    }
}

正如你在示例代码中看到的,我们定义了一个私有静态属性 $instance 来保存对象引用。由于这是静态的,因此该引用在此类型的所有对象之间共享。

getInstance() 方法使用一种称为延迟实例化的方法来将对象延迟到最后可能的时刻,因为你不希望未使用的内存中存在未使用的对象。它还节省了页面加载的时间和 CPU,而不必加载超过必要的对象。该方法是检查对象是否已设置,如果没有则创建它,并返回它。这确保了只创建了这种对象。

我们还将构造函数设置为私有,以确保没有人使用外部的 new 关键字创建它。如果你需要继承此类,只需将 private 关键字更改为 protected 即可。

要使用此对象,你只需编写以下内容:

$singleton = Singleton::getInstance();

现在我恳请你尽可能使用依赖注入,并针对松散耦合的对象,但有时候这是不合理的,单例模式可以使用。