30. Il metodo Magico __set()
Overload di __set()
Prototipo della funzione :
void __set (string name, mixed value)
|
Questo metodo ci consente di effettuare delle operazioni di assegnazione tradizionali sugli attributi della classe. Il primo parametro è il nome dell'attributo mentre il secondo parametro rappresenta il valore da assegnare a tale attributo. Se ad esempio abbiamo un'istanza di una ipotetica classe "Oggetto" che ha definito il metodo __set(), questo sarà richiamato quando verrà effettuata un'operazione di assegnazione ad un attributo della classe non esistente o non accessibile (private o protected), passando alla funzione i soliti due parametri, il nome dell'attributo sotto forma di stringa e il valore da assegnargli. |
Esempi di overloading
<?php
class Oggetto
{
public function __set($attributo, $valore)
{ /* Corpo funzione */ }
}
$obj = new Oggetto();
$obj->pippo = 32;
?>L'ultima riga di codice quindi ($obj->pippo = 32), corrisponde ad una chiamata al metodo __set() con
questi parametri : __set("pippo", 32);
Questo accade perchè nella definizione della classe "Oggetto", non abbiamo dichiarato nessun attributo di nome "pippo".
Vediamo un esempio più complesso :
<?php
class Stringa
{
private $stringa;
const MAX_CHARS = 15;
public function Stringa($valore)
{
if (strlen($valore) > self::MAX_CHARS)
{ throw new Exception("Stringa troppo lunga (max " . self::MAX_CHARS . " car.)"); }
else
{ $this->stringa = $valore; }
}
public function __set($attributo, $valore)
{
if ($attributo == "stringa")
{ self::Stringa($valore); }
else
{ throw new Exception("Attributo non esistente!"); }
}
public function __toString()
{ return $this->stringa; }
}
try
{
$obj = new Stringa("Ciao ciao!!!");
echo "$obj<br>\n"; // Stampa "Ciao ciao!!!"
$obj->stringa = "Ancora ciao!";
echo "$obj<br>\n"; // Stampa "Ancora ciao!"
$obj->stringa = "Un ultimo saluto!";
echo "$obj<br>\n"; // Solleva un'eccezione con il messaggio : "Stringa troppo lunga (max 15 car.)"
}
catch (Exception $e)
{
echo $e->getMessage();
}
?>|
Nell'esempio soprastante ho impostato l'attributo $stringa della classe Stringa come privato, attraverso il modificatore di accesso private. Poi ho reso l'attributo accessibile dall'esterno attraverso l'overload del metodo __set(), che in questo caso ho usato per simulare un accesso all'attributo di tipo public. Questo mi consente di effettuare dei controlli precisi sui valori assegnati all'attributo $stringa, senza comunque perdere la trasparenza e la comodità della classica operazione di assegnamento, tipica degli attributi public. A seguire un ultimo esempio, dove gestirò gli attributi della classe "Coordinata", come se fossero degli attributi normali memorizzandoli invece in un unico attributo di tipo Array. |
Il questo modo avremo la sicurezza che venga sempre effettuato un casting esplicito di tipo float durante l'assegnazione dei valori, e risparmieremo inoltre righe di codice durante la gestione degli pseudo-attributi potendo utilizzare una semplice foreach per scorrerli tutti, creando del codice rapido e più flessibile.
<?php
// Inizio dichiarazione Classe
class Coordinata
{
private $xyz;
public function Coordinata($x, $y, $z)
{
$this->xyz = array();
$this->xyz["x"] = (float) $x;
$this->xyz["y"] = (float) $y;
$this->xyz["z"] = (float) $z;
}
public function __set($attributo, $valore)
{
switch ($attributo)
{
case "x" :
case "y" :
case "z" :
$this->xyz[$attributo] = (float) $valore;
break;
default :
throw new Exception("Attributo non valido!");
break;
}
}
public function __toString()
{
$return = "";
foreach ($this->xyz as $chiave => $valore)
$return .= "$chiave = $valore<br />\n";
$return .= "<br>\n";
return $return;
}
}
// Fine dichiarazione Classe
try
{
$punto = new Coordinata(15, 17.3, 22.4);
echo $punto;
$punto->x = 20.3;
$punto->z = 11.2;
echo $punto;
$punto->a = 22.1; // L'attributo "a" non esiste e sarà sollevata un'eccezione
}
catch (Exception $e)
{ echo $e->getMessage(); }
?>Il codice soprastante produrrà questo risultato.
- Linguaggi:
- Tags:
