В классе PHP5, когда вызывает вызов частного конструктора?

Допустим, я пишу класс PHP (> = 5.0), который должен быть синглом. Все документы, которые я прочитал, говорят, чтобы сделать конструктор класса закрытым, чтобы класс не мог быть непосредственно создан.

Поэтому, если у меня есть что-то вроде этого:

class SillyDB { private function __construct() { } public static function getConnection() { } } 

Существуют ли случаи, когда __construct () вызывается иначе, чем если я делаю

 new SillyDB() 

вызвать внутри самого класса?

И почему мне разрешено создавать экземпляр SillyDB внутри себя?

__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 для подключения к базе данных гарантирует, что ваше приложение не будет создавать тонну соединений DB за раз.

Вот очень простой синглтон, который просто генерирует строку даты / времени:

 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() { } } 

Хорошо, я провела тесты самостоятельно.

  • Если вы не объявляете свой собственный конструктор в подклассе, попытка его создания будет генерировать фатальную ошибку, поскольку она пытается вызвать конструктор суперкласса.
  • В случае соединения с БД, когда вы предположительно возвращаетесь (в PHP, в любом случае) экземпляр mysqli или ресурс, возвращаемый функцией mysql_connect() (или какой-либо другой ссылкой на некоторые другие СУБД), пока вы отмечаете экземпляр private, нет угрозы, чтобы кто-то подклассифицировал его и искал ссылку.
  • Как я уже упоминал ранее, если кто-то действительно хочет переопределить ваше поведение и сделать несколько соединений, они могут так же хорошо сделать это, написав новый класс.

Проверьте код, Марк, и дайте мне знать, что вы узнали.

EDIT: Кроме того, в этой конкретной ситуации я не уверен, почему вам нужно будет беспокоиться о том, чтобы препятствовать человеку в подклассе. Если у кого-то есть доступ к вашему PHP-коду для подкласса, то у них также есть доступ к вашему коду, чтобы скопировать его и изменить модификаторы доступа на то, что они (по какой-либо причине) находят подходящим.

Практическая полезность Singleton в этом случае заключается в том, что, используя это, вы можете гарантировать, что вы всегда используете одно и то же соединение с базой данных для данного HTTP-запроса. Он это выполняет. Другой материал (с использованием final и частных конструкторов) полезен для понимания с точки зрения теории и еще более полезно знать, хотите ли вы распространять код качества API для других программистов, но в случае этого конкретного примера все ключевые слова делают добавление байтов в размер файла вашего класса.

Небольшая выборка: для полноты вы, вероятно, объявите класс окончательным, так как вы не хотите, чтобы кто-то подклассифицировал этот класс и реализовал свой собственный публичный конструктор.

(Простите меня, если компилятор ловит переопределение частного конструктора, но я не думаю, что это так)