【问题标题】:What does new self(); mean in PHP?new self(); 是什么意思?在 PHP 中是什么意思?
【发布时间】:2011-01-24 16:22:04
【问题描述】:

我从未见过这样的代码:

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

new className()一样吗?

编辑

如果类是继承的,它指向哪个类?

【问题讨论】:

  • @stereofrog,你的意思是应该放弃单例模式吗?但所有事物的存在都是有原因的,对吧?
  • 哦,我倾向于同意这一点:单例应该被工厂替换
  • @stereofrog Singleton 对单元测试来说是有毒的,很难对从一个调用到下一个调用改变状态的东西进行不可变测试。
  • 很遗憾,这个方法不会扩展。它总是会从定义此函数的类中为您提供一个新对象。

标签: php class self


【解决方案1】:

self 指向编写它的类。

因此,如果您的 getInstance 方法位于类名 MyClass 中,则以下行:

self::$_instance = new self();

会做同样的事情:

self::$_instance = new MyClass();


编辑:在 cmets 之后提供更多信息。

如果你有两个相互扩展的类,你有两种情况:

  • 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 这就是为什么 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] 页面。

【讨论】:

  • @Paul : heu... 的意思是“自我充当别名”,或“自我指向”——法语中的“设计师”动词可以用于—— - 我想这是在英语中使用同一个词不是一个好主意的情况之一;-(我会编辑我的答案来解决这个问题;;谢谢 :-)
  • 如果有baseclass,class,它指向哪一个?
  • @user :我已经编辑了我的答案,以提供有关self 和继承的更多信息;我还在 PHP 5.3 中包含了一些关于static 的信息;;希望这会有所帮助:-)
【解决方案2】:

是的,就像new className()(指包含该方法的类),可能用于构造函数为私有的单例模式中。

【讨论】:

  • 为什么有人会在 PHP 中使用单例模式?除非在类似守护进程的程序中使用,否则单例只会在脚本运行时存在,然后随着程序消失。
  • 避免烦人地声明 global 来访问全局变量
【解决方案3】:

这似乎是Singleton pattern 的实现。 该函数被静态调用并检查静态类是否设置了变量$_instance

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

如果您调用className::getInstance(),您将在每次调用时获得相同的类实例,这就是单例模式的重点。

不过,我从来没有见过这样的做法,老实说,我也不知道这是可能的。 $_instance 在类中声明的内容是什么?

【讨论】:

  • $_instance 被声明为public static $_instance;
【解决方案4】:

这很可能用在单例设计模式中,其中构造函数被定义为私有以避免被实例化,双冒号(::)运算符可以访问类内部声明为静态的成员,所以如果有静态成员,伪变量 $this 不能使用,因此代码使用 self 代替,单例是很好的编程实践,它只允许像数据库连接器处理程序这样的对象的 1 个实例。从客户端代码中,访问该实例将通过创建单个访问点来完成,在这种情况下,他将其命名为 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();

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

【讨论】:

    【解决方案5】:

    如果类是继承的,那么从 child 调用 getInstance() 不会给你一个 child 的实例。它只会返回父实例的一个实例。 这是因为我们调用了 new self()。

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

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2011-08-12
      相关资源
      最近更新 更多