PHP $this,自身和静态以及单例

示例

使用$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 "再见 ".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引用Car该类brand()。

要引用正确的类,您需要使用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();

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

未知的
宝马
奔驰

另请参阅后期静态绑定

单身人士

如果您的对象创建或表示与要重用的某些外部资源的连接很昂贵,即没有连接池或其他系统的套接字的数据库连接,则可以在类中使用staticandself关键字来使其单身。对于是否应该使用单例模式,存在强烈的意见,但是确实有其用途。

class Singleton {
    private static $instance = null;

    public static function getInstance(){
        if(!isset(self::$instance)){
            self::$instance = new self();
        }
        
        return self::$instance;
    }
    
    private function __construct() {
        // 做构造器的东西
    }
}

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

该getInstance()方法使用一种称为惰性实例化的方法将创建对象的时间延迟到了最后一个可能的时刻,因为您不希望将未使用的对象放在内存中而不打算使用。它还节省了时间,并且页面加载时的CPU不必加载过多的对象。该方法是检查是否设置了对象,如果没有设置则创建它,然后返回它。这样可以确保仅创建一个此类对象。

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

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

$singleton = Singleton::getInstance();

现在,我恳请您使用依赖注入,您可以在这里使用并瞄准松散耦合的对象,但这有时并不合理,并且可以使用单例模式。