45 OOP Oggetti 3 – costruttori e distruttori

Il costruttore (in php se ne può definire solo 1 per classe), è un metodo che  permette di instanziare una classe. viene definito come gli altri metodi aggiungendo la keyword __construct. Data la precedente classe prodotto:

class Prodotto
{
 //stato interno
  private
  $nome="Indefinito",
  $prezzo=0, $validoFinoAl="2000-01-01", $prezzoBloccato=false,
  $iva=22; 
 
 //metodi getter e setter 

 private function prezzoValido()
 {
 if (date("Y-m-d")<=$this->validoFinoAl)
    return true;
 else
    return false;
 }
 
 //restituisce -1 se il prezzo non è più valido
 public function getPrezzo()
 {
 if ( $this->prezzoValido() )
 return $this->prezzo;
 else
 return -1;
 }
 
 public function setPrezzo($nuovoPrezzo, $nuovaDataValidita)
 {
 if ( !$this->prezzoBloccato && $nuovaDataValidita>=date("Y-m-d"))
    $this->prezzo = $nuovoPrezzo;
 }

 public function stampa()
 {
 echo date("d-m-Y")." Scheda per il prodotto $this->nome"
 . io::NL;
 echo io::linea("-", 70) . io::NL;
 echo "PREZZO: $this->prezzo" . io::NL ;
 echo "IVA: $this->iva% " . io::NL;
 echo io::linea("-", 70) . io::NL;
 } 
}

aggiungiamo dentro la classe il costruttore pubblico

 //costruttore
 public function __construct($nome, $prezzo, $validoFinoAl)
 {
 $this->nome = $nome;
 
 $this->setPrezzo($prezzo, $validoFinoAl);
 }

Come si vede, il costruttore, come tutte le funzioni, può prevedere dei parametri. Per creare l’oggetto non potrò più come prima, usare la solita forma: $prodotto = new Prodotto, ma dovrò obbligatoriamente inserire i valori dei 3 parametri nell’oggetto, riferiti al costruttore:

$prodotto = new Prodotto("TonerXK09T",85,"2015-07-31");

A questo punto l’oggetto $prodotto, parte ben formato. Il costruttore al suo interno può fare tutti gli assegnamenti del caso

($this->nome = $nome;)

e controlli necessari. Infatti se è già incluso un metodo setter, non deve essere ridefinito, basterà richiamare tale metodo.

($this->setPrezzo($prezzo, $validoFinoAl);)

I parametri da inserire nel costruttore non devono per forza essere tanti quante sono le proprietà della classe, ma solo quelle necessarie alla corretta formazione dell’oggetto. Visto che in php si può definire solo 1 costruttore per classe, supponiamo però volessimo costruire un oggetto, definendo solo alcuni parametri del costruttore, per esempio solo il nome e il prezzo, la soluzione è creare un metodo public static, contenente i 2 parametri, sempre riferita al costruttore:

public static function da_dati_minimi($nome, $prezzo)
{
return new Prodotto($nome, $prezzo, date("Y-m-d"));
}

Questo metodo, da_dati_minimi, con soli 2 argomenti (nome e prezzo), crea un nuovo oggetto contenente i 2 parametri e il terzo necessario al costruttore lo fa generare (in questo caso utilizzo la funzione built-in date). A questo punto creo un altro metodo con tutti i dati necessari:

public static function da_dati_completi($nome, $prezzo, $validoFinoAl)
{
return new Prodotto($nome, $prezzo, $validoFinoAl);
}

Questo ultimo metodo pubblico, è una sorta di finto costruttore, o comunque richiede gli stessi parametri, questo mi permette di rendere il mio costruttore privato, evitando eventuali errori:

private function __construct($nome, $prezzo, $validoFinoAl)
{
$this->nome = $nome;

$this->setPrezzo($prezzo, $validoFinoAl);
}

Come fatto con questi 2, posso crearmi tanti metodi/finti_costruttori che mi aiutano nella creazione degli oggetti.

A questo punto non è più possibile creare l’oggetto col suo costruttore, ma con i metodi statici:

$prodotto2 = Prodotto::da_dati_minimi("prodotto minimo", 1);

oppure

$prodotto = Prodotto::da_dati_completi("TonerXK09T",85,"2015-07-31");

Esiste anche la possibilità di creare un distruttore, definito dalla keyword __destruct, che permette

//distruttore
 public function __destruct()
 {
 //rilascio risorse
 }

Il distruttore viene invocato in automatico dal programma, non devi essere tu, programmatore, a ricordarti che un determinato oggetto deve morire, quando magari termina una funzione che l’aveva creato, o magari dopo il suo inserimento in un database. Questo permette di liberare risorse al sistema.