2010-03-07 49 views
80

我从来没有见过代码:什么是新self();意味着在PHP?这样

public static function getInstance() 
{ 
    if (! isset(self::$_instance)) { 
     self::$_instance = new self(); 
    } 
    return self::$_instance; 
} 

是不是一样new className()

编辑

如果该类inheritant,它指向哪个班?

+0

http://stackoverflow.com/questions/151969/php-self-vs-this – 2010-03-07 13:42:21

+0

@ stereofrog,你的意思是单身模式应该放弃吗?但是所有的事情都存在是有原因的,对吗? – user198729 2010-03-07 16:06:31

+0

噢,我倾向于同意这一点:单身人士应该被工厂取代 – user198729 2010-03-07 16:55:12

回答

164

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 - 即在这里,它写在其中的类




随着PHP < 5.3, “在其所在的类” 是很重要的 - 有时可能会引起问题。

这就是为什么PHP 5.3引入了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关键字。


而且,谈到PHP 5.3,您可能需要查看PHP手册的Late Static Bindings页面。

+1

+1,但我认为你的意思是“表示”而不是“设计”? – 2010-03-07 13:44:44

+0

@Paul:heu ...意思是“自我作为别名”,或者“自我排序” - 法语中的“设计师”动词可以用于这一点 - 我想这是其中之一在英语中使用相同单词的情况并不是一个好主意;-(我将编辑我的答案以解决此问题;;感谢:-) – 2010-03-07 13:47:11

+0

如果有'baseclass','class',那么它会指向哪一点至? – user198729 2010-03-07 14:04:41

1

是的,它就像new className()(指包含该方法的类),可能用于构造函数为private的Singleton模式。

+0

正是!构造函数是私有的! – user198729 2010-03-07 13:43:41

+0

为什么有人会在PHP中使用Singleton模式?除非在类似守护程序的程序中使用,否则单例只能在脚本运行时存活,然后随程序一起消失。 – ILikeTacos 2013-10-16 21:07:18

+2

避免恼人地声明全局变量访问全局变量 – 2014-12-15 17:16:03

9

这似乎是Singleton pattern的执行。 该函数被静态调用并检查静态类是否具有设置的变量$_instance

如果不是,它会初始化其本身的一个实例(new self())并将其存储在$_instance中。

如果您致电className::getInstance(),您将在每次调用时得到一个和相同的类实例,这是单例模式的要点。

虽然我从来没有见过这样做,但老实说,不知道这是可能的。 什么是$_instance在班级中声明?

+1

'$ _instance'被声明为'public static $ _instance;' – Atif 2014-12-07 09:53:52

6

这很可能用于单例设计模式,其中构造函数被定义为私有的,以避免被实例化,双冒号(::)运算符可以访问在类内声明为静态的成员,所以如果存在静态成员,伪变量$ this不能使用,因此代码使用self而不是Singletons,它是很好的编程实践,它只允许1个对象的实例,如数据库连接器处理程序。从客户端代码,访问该实例将通过创建一个单一的访问点完成,在这种情况下,他将其命名为getInstance(),getInstance本身就是创建对象的函数,基本上使用new关键字创建一个对象,这意味着构造方法也被称为。

if(!isset(self::instance))检查对象是否已经被创建,你无法理解这个监守的代码只是一个片段,在顶部的地方,应该有静态成员一样可能

private static $_instance = NULL; 
正常

班我们会通过简单的

$this->_instance = 'something'; 

访问这个成员,但其声明为static,所以我们不能使用$此代码,我们改用

self::$_instance 

通过检查这个静态类变量是否存在一个对象,这个类可以决定是否创建一个实例,所以如果它没有设置,!isset,意味着静态成员上不存在对象$ _instance,那么它由命令

self::$_instance = new self(); 

生成新的对象,其存储在静态成员$_instance,并将其返回给客户端的代码。客户端代码然后可以愉快地使用对象的单个实例与其公共方法,但在客户端代码中,调用单个访问点,也就是getInstance()方法也很棘手,它必须像这样调用

$thisObject = className::getInstance(); 

原因,该函数本身被声明为静态的。

0

如果该类是继承的,那么从子项调用getInstance()将不会为您提供子实例。它只会返回父实例的一个实例。 这是因为我们称之为新self()。

如果您希望子类将返回子类的实例,请在getInstance()中使用new static(),然后它将返回子类实例。这被称为晚期绑定!