In una classe PHP5, quando viene chiamato un costruttore privato?
-
09-06-2019 - |
Domanda
Diciamo che sto scrivendo una classe PHP (>= 5.0) che dovrebbe essere un singleton.Tutti i documenti che ho letto dicono di rendere privato il costruttore della classe in modo che la classe non possa essere istanziata direttamente.
Quindi, se ho qualcosa del genere:
class SillyDB
{
private function __construct()
{
}
public static function getConnection()
{
}
}
Ci sono casi in cui viene chiamato __construct() diverso da quando sto eseguendo a
new SillyDB()
chiamare all'interno della classe stessa?
E perché mi è consentito creare un'istanza di SillyDB dall'interno di se stesso?
Soluzione
__construct()
verrebbe chiamato solo se lo chiamassi dall'interno di un metodo per la classe contenente il costruttore privato.Quindi per il tuo Singleton, potresti avere un metodo come questo:
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();
Il motivo per cui puoi/vorresti creare un'istanza della classe dall'interno di se stessa è che puoi verificare che esista solo un'istanza alla volta.Dopotutto, questo è il punto centrale di Singleton.L'utilizzo di un Singleton per una connessione al database garantisce che l'applicazione non effettui molte connessioni DB alla volta.
Modificare: Aggiunto $, come suggerito da @emanuele-del-grande
Altri suggerimenti
Ecco un singleton molto semplice che genera semplicemente una stringa di data/ora:
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");
}
}
Fare qualcosa del genere ovviamente mi dà sempre la stessa data:
$date1 = TheDate::getDateInstance();
echo $date1->getDateVal() . "<br />";
$date2 = TheDate::getDateInstance();
echo $date2->getDateVal() . "<br />";
E fare questo non genera alcun errore:
class NewDate extends TheDate
{
public function __construct()
{
}
}
OK, ho eseguito alcuni test per conto mio.
- Se non dichiari il tuo costruttore nella sottoclasse, provare a istanziarlo genererà un errore fatale, perché tenta di chiamare il costruttore della superclasse.
- Nel caso di una connessione DB, quando presumibilmente stai restituendo (in PHP, comunque) un'istanza mysqli o la risorsa restituita da
mysql_connect()
funzione (o qualche altro collegamento a qualche altro RDBMS), finché si contrassegna l'istanza come privata, non vi è alcun pericolo che qualcuno la sottoclassi e manometta il collegamento. - Come ho accennato prima, se qualcuno vuole davvero sovrascrivere il tuo comportamento e creare più connessioni, potrebbe farlo anche scrivendo una nuova classe.
Prova il codice, Mark, e fammi sapere cosa scopri.
MODIFICARE:Inoltre, in questa particolare situazione, non sono sicuro del motivo per cui dovresti preoccuparti di impedire a una persona di creare sottoclassi.Se qualcuno ha accesso al tuo codice PHP per sottoclassarlo, allora avrà anche accesso al tuo codice per copiarlo e modificare i modificatori di accesso in qualcosa che (per qualsiasi motivo) trova adatto.
L'utilità pratica del Singleton in questo caso è che, utilizzandolo, puoi assicurarti di utilizzare sempre la stessa connessione al database per una determinata richiesta HTTP.Lo realizza.Le altre cose (usando final
e costruttori privati) è utile conoscerlo da un punto di vista teorico, e ancora più utile sapere se si desidera distribuire codice di qualità API ad altri programmatori, ma nel caso di questo esempio particolare, tutto ciò che le parole chiave stanno facendo è aggiungere byte a la dimensione del file della tua classe.
Un po' di pignoleria:Per completezza probabilmente lo faresti dichiarare la lezione come definitiva anche dal momento che non vorresti che qualcuno sottoclassasse questa classe e implementasse il proprio costruttore pubblico.
(Perdonami se il compilatore rileva l'override di un costruttore privato, ma non credo che lo faccia)