我从未见过这样的代码:
public static function getInstance()
{
if ( ! isset(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
是一样的new className()
吗?
编辑
如果类是继承的,它指向哪个类?
self
指向编写它的类。
因此,如果您的 getInstance 方法在类名MyClass
中,则以下行:
self::$_instance = new self();
会做同样的事情:
self::$_instance = new MyClass();
编辑:评论后提供更多信息。
如果您有两个相互扩展的类,则有两种情况:
getInstance
在子类中定义getInstance
在父类中定义第一种情况看起来像这样(对于这个例子,我已经删除了所有不必要的代码——你必须将它添加回来才能获得单例行为)*:
class MyParentClass {
}
class MyChildClass extends MyParentClass {
public static function getInstance() {
return new self();
}
}
$a = MyChildClass::getInstance();
var_dump($a);
在这里,您将获得:
object(MyChildClass)#1 (0) { }
这意味着self
意味着MyChildClass
- 即编写它的类。
class MyParentClass {
public static function getInstance() {
return new self();
}
}
class MyChildClass extends MyParentClass {
}
$a = MyChildClass::getInstance();
var_dump($a);
你会得到这种输出:
object(MyParentClass)#1 (0) { }
这意味着self
意味着MyParentClass
- 也就是在这里,它被写入的类。
static
关键字引入新用法的原因:它现在可以准确地用于我们self
在这些示例中使用的位置:
class MyParentClass {
public static function getInstance() {
return new static();
}
}
class MyChildClass extends MyParentClass {
}
$a = MyChildClass::getInstance();
var_dump($a);
但是,使用static
而不是self
,您现在将得到:
object(MyChildClass)#1 (0) { }
这意味着static
那种指向使用的类(我们使用MyChildClass::getInstance()
),而不是编写它的类。
当然,行为self
并没有改变,为了不破坏现有的应用程序——PHP 5.3 只是添加了一个新的行为,循环使用static
关键字。
这似乎是单例模式的实现。该函数被静态调用并检查静态类是否$_instance
设置了变量。
如果不是,它会初始化自身的一个实例 ( new self()
) 并将其存储在$_instance
.
如果您调用className::getInstance()
,您将在每次调用时获得一个相同的类实例,这就是单例模式的要点。
不过,我从来没有见过这样做的,老实说,我不知道这是可能的。类中声明的内容是什么$_instance
?
这很可能用在单例设计模式中,其中构造函数被定义为私有以避免被实例化,双冒号(::)
运算符可以访问类内部声明为静态的成员,因此如果有静态成员,则伪变量$这不能使用,因此代码使用 self 代替,单例是很好的编程实践,它只允许一个对象的实例,如数据库连接器处理程序。从客户端代码中,访问该实例将通过创建单个访问点来完成,在这种情况下,他将其命名为getInstance()
getInstance 本身就是创建对象的函数,基本上使用 new 关键字创建对象,这意味着构造方法是也被称为。
该行if(!isset(self::instance))
检查是否已经创建了一个对象,您无法理解这一点,因为代码只是一个片段,在顶部的某个地方,应该有像可能这样的静态成员
private static $_instance = NULL;
在普通类中,我们可以通过简单地访问该成员
$this->_instance = 'something';
但是它声明为静态的,所以我们不能使用我们使用的 $this 代码
self::$_instance
通过检查这个静态类变量上是否存储了一个对象,该类可以决定创建或不创建单个实例,所以如果它没有设置,!isset,意味着静态成员 $_instance 上不存在对象,然后它生成一个新对象,$_instance
通过命令将其存储在静态成员中
self::$_instance = new self();
并将其返回给客户端代码。然后客户端代码可以愉快地使用对象的单个实例及其公共方法,但是在客户端代码中,调用单个访问点,即getInstance()
方法也很棘手,必须这样调用
$thisObject = className::getInstance();
原因是函数本身被声明为静态的。
是的,它就像new className()
(指包含该方法的类),可能在构造函数是私有的单例模式中使用。
如果类是继承的,那么从 child 调用 getInstance() 不会给你一个 child 的实例。它只会返回父实例的一个实例。这是因为我们调用了 new self()。
如果您希望子类返回子类的实例,则在 getInstance() 中使用 new static(),然后它将返回子类实例。这叫做后期绑定!!