OOP

Funzioni variabili applicate agli Oggetti

Nell'ultima parte del capitolo sulle Funzioni, abbiamo parlato delle funzioni variabili.

Vedremo ora come è possibile applicare il medesimo concetto ai metodi di una classe.

<?php

	class OggettoInventato
	{
		function metodo1()
		{ echo "Ciao sono il primo metodo!<br />\n"; }

		function metodo2()
		{ echo "Ciao sono il secondo metodo!<br />\n"; }

		function metodo3()
		{ echo "Ciao sono il terzo metodo!<br />\n"; }
	}

	$obj = new OggettoInventato();

	$num = 3;
	$prefisso = "metodo";
	
	for ($i = 1; $i <= $num; $i++)
	{
		$funzione = $prefisso . $i;
		$obj->$funzione();
	}

?>

Il codice soprastante produce questo risultato.

Per richiamare i metodi con le variabili dall'interno della classe, è sufficiente sostituire $obj con $this.

<?php

	class OggettoInventato
	{
		function metodo1()
		{ echo "Ciao sono il primo metodo!<br />\n"; }

		function metodo2()
		{ echo "Ciao sono il secondo metodo!<br />\n"; }

		function metodo3()
		{ echo "Ciao sono il terzo metodo!<br />\n"; }

		function richiamaMetodi()
		{
			$num = 3;
			$prefisso = "metodo";
	
			for ($i = 1; $i <= $num; $i++)
			{
				$funzione = $prefisso . $i;
				$this->$funzione();
			}
		}
	}

	$obj = new OggettoInventato();
	$obj->richiamaMetodi();

?>

Il risultato ottenuto è il medesimo.

17. Oggetti e Costanti

PHP 5 ci consente di definire delle costanti all'interno delle classi.
L'utilizzo è simile alle costanti globali descritte nel nono capitolo di questa guida.

Potete pensare alle costanti delle classi, come a degli attributi statici che non possono però essere modificati una volta dichiarati e definiti.

Prendiamo nuovamente in esempio la vecchia classe "Colore" esaminandone un utilizzo con le costanti :

Colore.php

<?php

	class Colore
	{
		const ROSSO = "#FF0000";
		const VERDE = "#00FF00";
		const BLU = "#0000FF";

		static public function stampaRosso()
		{
			echo "<font color=\"" . self::ROSSO . "\">Il valore esadecimale del colore rosso è : ";
			echo self::ROSSO . "</font><br />\n";
		}
	}

?>

Come con le costanti globali è necessario omettere il simbolo del dollaro $ durante la dichiarazione.
I nomi delle costanti in PHP 5 sono sempre Case Sensitive, ed è buona norma scriverle tutte in maiuscolo per distinguerle immediatamente come costanti, anche se non è obbligatorio.

test.php

<?php

	require_once("Colore.php");

	echo Colore::ROSSO . "<br />\n";
	Colore::stampaRosso();

?>

test.php produce questo risultato.

16. Gli Oggetti e i Membri statici

Prima di introdurre il concetto dei membri statici, è necessario sapere che per utilizzare un membro di una classe, un attributo o un metodo, è obbligatorio creare un'istanza di tale classe attraverso la parola chiave new, come illustrato nel capitolo precedente.

$utente = new Persona("John", "Doe", "1-1-1970");

In questo modo, ogni istanza della classe avrà la propria copia di ogni attributo e ogni metodo.

Talvolta può risultare utile voler rendere accessibile un membro di una classe senza doverne inizializzare un'istanza, e questo è appunto possibile dichiarando il membro come statico.

Per capire meglio, prendiamo un esame un'ipotetica classe "Colore", che avrà una serie di colori di base che sarà utile rendere accessibili sempre, anche quando effettivamente non ci sarà utile creare un'istanza della suddetta classe.

Colore.php

<?php

	class Colore
	{
		static $rosso = "#FF0000";
		static $verde = "#00FF00";
		static $blu = "#0000FF";

		/*
			... altri attributi
		*/

		public function Colore()
		{ /* codice costruttore */ }

		/*
			... altri metodi
		*/

		static public function stampaColore($colore)
		{
			echo "<font color=\"" . Colore::${$colore} . "\">Il valore esadecimale del colore $colore è : ";
			echo Colore::${$colore} . "</font><br />\n";
		}
	}

?>

Ora che abbiamo dichiarato la nostra nuova classe Colore, vediamo come è possibile utilizzare i suoi 3 attributi statici.
E' sufficiente specificare il nome della classe seguito dai doppi due punti e il nome del membro :

test.php

<?php

	require_once("Colore.php");

	echo "<font color=\"" . Colore::$rosso . "\">Il valore esadecimale del colore rosso è : ";
	echo Colore::$rosso . "</font><br />\n";

	echo "<font color=\"" . Colore::$verde . "\">Il valore esadecimale del colore verde è : ";
	echo Colore::$verde . "</font><br />\n";

	echo "<font color=\"" . Colore::$blu . "\">Il valore esadecimale del colore blu è : ";
	echo Colore::$blu . "</font><br />\n";

?>

Richiamando la pagina test.php, otterremo questo risultato.

Se in un secondo momento decidiamo che per il nostro sito è più adatto un rosso scuro, sarà sufficiente assegnarvi tale valore all'inizio dello script, rendendo così effettiva la modifica in tutto il codice, senza peraltro modificare la classe che potrebbe essere condivisa con altre applicazioni anche esterne al server.

Nell'esempio che segue, stavolta utilizzeremo il metodo statico "stampaColore()" per visualizzare i colori sul browser.

test.php

<?php

	require_once("Colore.php");

	Colore::stampaColore("rosso");

	Colore::$rosso = "#C11C1C"; // Rosso più scuro

	Colore::stampaColore("rosso");

?>

L'esempio soprastante genera questo risultato.

Per accedere ai membri statici dall'interno della classe, $this non è adeguato e genera il seguente errore :
Fatal error: Using $this when not in object context in C:\AppServ\www\test\Colore.php

Il modo corretto per accedervi dall'interno è mediante il costrutto self :

<?php

	class Colore
	{
		static $rosso = "#FF0000";

		// ...

		static public function stampaColore($colore)
		{
			self::$rosso = "#FF0000";

			echo "<font color=\"" . Colore::${$colore} . "\">Il valore esadecimale del colore $colore è : ";
			echo Colore::${$colore} . "</font><br />\n";
		}
	}

?>

Concludo il capitolo con una nota per chi è già avvezzo con il concetto dell'ereditarietà.
Se accedete a un membro statico della classe madre all'interno della figlia, ricordatevi di sostituire self con parent.

15. Oggetti

Introdurrò ora uno dei concetti più importanti di PHP 5 : gli Oggetti.

La programmazione orientata agli oggetti è alla base di ogni applicazione solida e potente, e ci consentirà di scrivere del codice estremamente flessibile ed elastico, facendoci risparmiare talvolta anche ore ed ore di lavoro.

Possiamo pensare ad un oggetto come ad un tipo di dato più complesso e personalizzato, non esistente fra i tipi tradizionali di PHP, ma bensì ideato e creato da noi.

Lo scopo è quello di creare un tipo di dato più complesso, per soddisfare richieste che potremo comunque adempiere con i tipi tradizionali, ma con molta meno difficoltà e tempo.

Gli oggetti sono formati principalmente da attributi e metodi.

Gli attributi sono delle variabili proprietarie dell'oggetto, semplici o complesse, quindi anche Array o Oggetti.

I metodi invece, sono delle funzioni proprietarie dell'oggetto, e fra questi ce ne sono due molto importanti :
i Costruttori e i Distruttori.

Se non definirete un costruttore e un distruttore per la vostra classe (oggetto), PHP li rimpiazzerà con dei metodi propri di default, in quanto questi due metodi sono essenziali per il corretto fuzionamento della classe.

Il costruttore verrà chiamato automaticamente da PHP, ogni volta che verrà creato un oggetto (istanza), mentre il distruttore sarà chiamato quando l'oggetto verrà distrutto, ossia quando non esiste più alcun riferimento all'oggetto oppure alla fine dello script.

Per dichiarare un costruttore, è sufficiente creare una funzione all'interno della classe che abbia lo stesso nome di quest'ultima, oppure potete usare la parola chiave __construct().

Nell'esempio che segue creeremo un nuovo tipo di dato, l'oggetto "Persona", con gli attributi "nome", "cognome" e "data di nascita" e il metodo "stampaPersona()" per visualizzare i dati sul browser. Per creare la nuova classe utilizzeremo il costrutto del linguaggio class :


Persona.php

<?php

	class Persona
	{
		public $nome = ""; // attributo
		public $cognome = ""; // attributo
		public $datanascita = ""; // attributo

		public function Persona($n_nome, $n_cognome, $n_data) // costruttore
		{
			$this->nome = $n_nome;
			$this->cognome = $n_cognome;
			$this->datanascita = $n_data;
		}

		public function stampaPersona() // metodo
		{
			echo "Nome : " . $this->nome . "<br />\n";
			echo "Cognome : " . $this->cognome . "<br />\n";
			echo "Data di nascita : " . $this->datanascita . "<br />\n";
		}
	}

?>

Come potete notare il nome del file è uguale a quello della classe, così come lo è il nome del costruttore.
Il costruttore prende in input tre parametri ($n_nome, $n_cognome, $n_data) che andrà a memorizzare rispettivamente nei propri attributi ($nome, $cognome, $datanascita), a cui accederà tramite la parola chiave this.

Con this l'oggetto può richiamare i suoi attributi e metodi, in quanto this indica l'oggetto stesso.
Subito dopo this segue l'operatore di selezione -> che punta ad un determinato attributo o metodo alla sua destra, appartenente all'oggetto alla sua sinistra (this).

Ricordate sempre che in questi casi, il simbolo del dollaro $, va solo su this e non sul nome dell'attributo/metodo, a meno che non si stia usando il metodo delle variabili funzione, di cui discuteremo la variante per oggetti nei prossimi capitoli.

Infine troviamo il metodo stampaPersona() che semplicemente stampa gli attributi dell'oggetto tramite il costrutto echo.

La parola chiave public sarà illustrata nel prossimo capitolo assieme a protected e private.

Ora vedremo come creare ed utilizzare un'istanza dell'oggetto "Persona" dichiarato nella pagina precedente.

test.php

<?php require_once("Persona.php"); ?>
<html>

	<head>
		<title>Test</title>
	</head>

	<body>
	<?php

		$utente = new Persona("Mario", "Rossi", "10-01-1980");
		$utente->stampaPersona();

	?>

	</body>
</html>

Il codice soprastante produce questo risultato.
Per creare una nuova istanza della classe "Persona", abbiamo usato la parola chiave new seguita dal costruttore della classe con i rispettivi parametri.
A seguire richiamiamo il metodo "stampaPersona()" con l'operatore di selezione -> descritto in precedenza.

Osservando la classe nell'esempio della pagina precedente "Persona.php", possiamo notare che tutti gli attributi, il costruttore e il metodo, sono dichiarati con la parola chiave public.

Questo ci consente di usarli e richiamarli liberamente nello script attraverso un'istanza della suddetta classe. La parola chiave public è un modificatore di accesso, che serve a stabilire che tipo di restrizioni si devono avere lavorando su quel dato.

Public, Protected e Private

Di seguito una breve descrizione di public e le sue varianti protected e private :

  • public - I membri (attributi o metodi) della classe dichiarati public, possono essere utilizzati sia all'interno che all'esterno della classe madre e di quelle derivate da essa (ereditarietà) ($this->membro oppure $oggetto->membro)
  • protected - I membri dichiarati protected, possono essere utilizzati solo all'interno delle classi madri e derivate ($this->membro)
  • private - I membri dichiarati private, possono essere utilizzati solo all'interno della classe madre ($this->membro)

Tornando alla classe "Persona", poichè abbiamo dichiarato gli attributi come public, il linguaggio ci consente di agire direttamente su di essi, senza dover richiamare il costruttore ogni volta che dobbiamo modificare un attributo dell'istanza ($utente) :

$utente = new Persona("John", "Doe", "1-1-1970");

$utente->nome = "Santiago";
$utente->cognome = "Arnavisca";

$utente->stampaPersona(); // output = Nome : Santiago / Cognome : Arnavisca / Data di nascita : 1-1-1970

Se invece avessimo usato la restrizione private per gli attributi della classe "Persona", avremmo ricevuto dal server il seguente errore sollevato dalla riga $utente->nome = "Santiago";
Fatal error: Cannot access private property Persona::$nome in C:\AppServ\www\test\test.php

Avremmo ottenuto un errore equivalente anche utilizzando il modificatore di accesso protected, in quanto protected stabilisce che l'attributo o metodo così dichiarato, può essere utilizzato solo all'interno della classe, ma a differenza di private, ne consente l'utilizzo anche nelle classi derivate, argomento che tratteremo più avanti nel capitolo della Ereditarietà.

Condividi contenuti