Сведения о вопросе

profi

17:17, 18th August, 2020

Теги

php   oop   constructor    

Когда в классе PHP5 вызывается частный конструктор?

Просмотров: 507   Ответов: 5

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

Так что если у меня есть что-то вроде этого:

class SillyDB
{
  private function __construct()
  {

  }

  public static function getConnection()
  {

  }
}

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

new SillyDB() 

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

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



  Сведения об ответе

davran

21:16, 11th August, 2020

__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();

Причина, по которой вы можете/хотели бы создать экземпляр класса из самого себя, заключается в том, что вы можете проверить, существует ли только один экземпляр в любой момент времени. В конце концов, в этом и заключается весь смысл a Singleton. Использование Singleton для подключения к базе данных гарантирует, что ваше приложение не создает тонны соединений DB одновременно.


Edit: добавлено $, как предложено @emanuele-del-grande


  Сведения об ответе

VCe znayu

12:16, 10th August, 2020

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

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

    }
}


  Сведения об ответе

KOMP

08:16, 25th August, 2020

Ладно, я сам провел несколько тестов.

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


  Сведения об ответе

dump

09:38, 23rd August, 2020

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

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

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


  Сведения об ответе

lool

13:31, 11th August, 2020

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться