假设我正在编写一个PHP(> = 5.0)类,它应该是一个单例。 我读过的所有文档都说使类构造函数变为私有,因此无法直接实例化类。

所以,如果我有这样的事情:

class SillyDB
{
  private function __construct()
  {

  }

  public static function getConnection()
  {

  }
}

是否有任何情况下__construct()被调用,而不是我正在做的事情

new SillyDB() 

在班级内部打电话?

为什么我被允许从内部实例化SillyDB呢?

===============>>#1 票数:62 已采纳

只有在包含私有构造函数的类的方法中调用它时,才会调用__construct() 所以对于你的Singleton,你可能有这样的方法:

class DBConnection
{
   private static $Connection = null;

   public static function getConnection()
   {
      if(!isset(self::$Connection))
      {
         self::$Connection = new DBConnection();
      }
      return self::$Connection;
   }

   private function __construct()
   {

   }
}

$dbConnection = DBConnection::getConnection();

您能够/希望从内部实例化类的原因是您可以检查以确保在任何给定时间只存在一个实例。 毕竟,这是单身人士的全部观点。 使用Singleton进行数据库连接可确保您的应用程序不会同时进行大量数据库连接。


编辑:根据@ emanuele-del-grande的建议添加$

===============>>#2 票数:6

这是一个非常简单的单例,它只生成一个日期/时间字符串:

class TheDate
{
    private static $DateInstance = null;
    private $dateVal;

    public static function getDateInstance()
    {
        if(!isset(self::$DateInstance))
        {
            self::$DateInstance = new TheDate();
        }

        return self::$DateInstance;
    }

    public static function getDateVal()
    {
        return self::$DateInstance->dateVal;
    }

    private function __construct()
    {
        $this->dateVal = strftime("%Y-%m-%d %H:%M:%S");
    }
}

做这样的事情显然会一遍又一遍地给我同样的日期:

$date1 = TheDate::getDateInstance();
echo $date1->getDateVal() . "<br />";

$date2 = TheDate::getDateInstance();
echo $date2->getDateVal() . "<br />";

这样做不会产生任何错误:

class NewDate extends TheDate
{
    public function __construct()
    {

    }
}

===============>>#3 票数:4

好的,我自己做了一些测试。

  • 如果你没有在子类中声明自己的构造函数,尝试实例化它将引发致命错误,因为它试图调用超类构造函数。
  • 在数据库连接的情况下,当您可能返回(在PHP中,无论如何)mysqli实例或mysql_connect()函数返回的资源(或其他一些链接到其他RDBMS)时,只要您标记实例私有,没有人威胁它继承它并篡改链接。
  • 正如我之前提到的,如果有人真的想要覆盖你的行为并建立多个联系,他们也可以通过编写一个新类来做到这一点。

===============>>#4 票数:2

测试代码,Mark,让我知道你发现了什么。

编辑:此外,在这种特殊情况下,我不确定为什么你需要关注防止一个人进行子类化。 如果有人可以访问您的PHP代码来对其进行子类化,那么他们也可以访问您的代码来复制它并将访问修饰符更改为他们(无论出于何种原因)找到合适的代码。

在这种情况下,Singleton的实际用途是,通过使用它,您可以确保始终对给定的HTTP请求使用相同的数据库连接。 它实现了这一点。 从理论角度来看,其他东西(使用final和private构造函数)很有用,知道是否要将API质量代码分发给其他程序员更有用,但在这个特定示例的情况下,所有关键字都是如此正在做的是添加字节到您的类文件的大小。

===============>>#5 票数:0

一点点挑选:为了完整性,您可能会将该类声明为final,因为您不希望有人继承此类并实现其自己的公共构造函数。

(如果编译器捕获到私有构造函数的覆盖,请原谅我,但我不认为它会这样做)

  ask by Mark Biek translate from so

未解决问题?本站智能推荐:

1回复

php OOP:在类的构造函数中做某事与调用私有方法做同样的事情

在阅读各种教程时,我注意到了这两种不同的方法,并且我对引擎盖下发生的事情感到好奇。 第一种方法在构造函数中执行所有操作-一切都在设置变量,或者在这种情况下,调用类的方法执行某项操作。 第二种方法在构造函数中调用私有方法来执行相同的操作。 什么时候比另一种方法更受青睐? 我知道微观优化
15回复

如何让PHP类构造函数调用其父级的父构造函数

我需要在PHP中使用类构造函数调用其父级的父级 (祖父级?)构造函数而不调用父构造函数。 我知道这是一件很奇怪的事情,我试图找到一种味道并不难闻的手段但是,我很好奇是否有可能。 编辑 我想我应该发布所选答案的理由。 原因是; 它是最优雅的解决方案,希望在保留所有值的同时调
2回复

可以在PHP类构造函数中运行查询吗?

这是我第一次使用PHP创建面向对象的站点,也是有关构造函数的问题。 我有一个用户登录后生成的角色类。角色对象将保存游戏的所有用户数据。 我的问题是关于构造函数/实例化类。 像我在所附代码中一样,可以在类构造函数中运行查询吗? 当前传递的参数只是登录期间获得的用户名,这是在查询
1回复

在PHP中调用父类构造函数

我有一个控制器 并在APIController APIController __construct()内部什么都没有被调用,我尝试了parent::__construct(); APIController __construct() 但是当我尝试从APIController调用
6回复

PHP [OOP] - 如何手动调用类构造函数?

请看下面的代码: 现在,问题是在09行调用构造函数 但我想在第11-13行手动调用它 可能吗? 如果那么怎么样? 有什么好主意吗?
1回复

在子构造函数中调用父构造函数

我只是好奇地知道,创建一个仅用于调用父构造函数的子类构造函数是否是一个好主意。 现在,在以下示例中,我们可以实现相同的目的: 题: 创建仅用于调用父构造函数的子构造函数是个好主意,还是这样做还有其他优点?
5回复

PHP中构造函数的目的

可能重复: 使用构造函数的好处? 你好编码员。 我是php OOP的新手。 我正在做一个对象和类的项目。 大部分时间我都面对面 我听不懂 为什么使用它,其价值是什么。 有人可以告诉我一下吗。 我去了php.net网站,但我的疑问没有消除。
1回复

php中的抽象类中构造函数的用途是什么?

我在问之前已经关注了这个链接 - 答案是在JAVA上下文中 ,这是用于PHP中的构造函数 。 由于我是首发,我在OOP概念中实现了我的PHP代码,因此我非常愿意了解PHP抽象类中的用法和好处或何时使用构造函数。 请在现实世界中提供一个示例,以便更好地掌握概念。 PS - 虽然我
2回复

如何在PHP的类构造函数中传递接口实例

我有以下课程 当我创建类对象时 如何传递接口实例?这是正确的编码方式吗?
5回复

什么时候我们应该让构造函数私有&为什么? PHP [重复]

可能重复: 在PHP5类中,何时调用私有构造函数? 我最近一直在阅读有关OOP的内容并遇到了这个私有构造函数的情况。 我做了Google搜索,但找不到与PHP相关的任何内容。 在PHP中 我们何时必须定义私有构造函数? 使用私有构造函数的目的是什么?