В классе PHP5, когда вызывает вызов частного конструктора?
Скажем, я пишу класс PHP ( >= 5.0), который должен быть синглом. Все прочитанные документы, чтобы сделать конструктор класса закрытым, чтобы класс не мог быть непосредственно создан.
Итак, если у меня есть что-то вроде этого:
class SillyDB
{
private function __construct()
{
}
public static function getConnection()
{
}
}
Существуют ли случаи, когда __construct() вызывается иначе, чем если я делаю
new SillyDB()
вызов внутри самого класса?
И почему мне разрешено создавать экземпляр SillyDB внутри себя?
Ответы
Ответ 1
__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 за раз.
Ответ 2
Здесь очень простой синглтон, который просто генерирует строку даты/времени:
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
Хорошо, я провел несколько тестов самостоятельно.
- Если вы не объявляете свой собственный конструктор в подклассе, попытка его создания вызовет фатальную ошибку, потому что он пытается вызвать конструктор суперкласса.
- В случае соединения с БД, когда вы предположительно возвращаете (в PHP, так или иначе) экземпляр mysqli или ресурс, возвращаемый функцией
mysql_connect()
(или некоторая другая ссылка на некоторые другие СУБД), до тех пор, пока вы помещаете экземпляр private, нет угрозы кому-то подклассифицировать его и подделывать ссылку.
- Как я уже упоминал ранее, если кто-то действительно хочет переопределить ваше поведение и сделать несколько подключений, они могли бы также сделать это, написав новый класс.
Ответ 4
Проверьте код, Марк, и дайте мне знать, что вы узнали.
EDIT: Кроме того, в этой конкретной ситуации я не уверен, почему вам нужно будет беспокоиться о том, чтобы предотвратить подкласс людей. Если у кого-то есть доступ к вашему PHP-коду для подкласса, то у них также есть доступ к вашему коду, чтобы скопировать его и изменить модификаторы доступа на то, что они (по какой-либо причине) находят подходящим.
Практическая полезность Singleton в этом случае заключается в том, что, используя это, вы можете гарантировать, что вы всегда используете одно и то же соединение с базой данных для данного HTTP-запроса. Он это выполняет. Другой материал (используя final
и частные конструкторы) полезен для понимания с точки зрения теории и еще более полезно знать, хотите ли вы распространять код качества API другим программистам, но в случае этого конкретного примера все ключевые слова делают добавление байтов в размер вашего класса.
Ответ 5
Небольшая выборка: для полноты вы, вероятно, объявите класс окончательным, так как вы не хотите, чтобы кто-то подклассифицировал этот класс и реализовал свой собственный публичный конструктор.
(Простите меня, если компилятор ловит переопределение частного конструктора, но я не думаю, что это делает)