# PHP/Programmazione/OOP

PHP
Copertina Tutti i moduli · Sviluppo
    CopertinaPHP/Copertina
* IntroduzionePHP/Introduzione
** StoriaPHP/Introduzione/Storia
** Come funzionaPHP/Introduzione/Come funziona
* Installazione e configurazionePHP/Installazione e configurazione
** InstallazionePHP/Installazione
*** LinuxPHP/Installazione/Linux
*** WindowsPHP/Installazione/Windows
*** Mac OS XPHP/Installazione/Mac OS X
** ConfigurazionePHP/Configurazione
* ProgrammazionePHP/Programmazione
** CommentiPHP/Programmazione/Commenti
** VariabiliPHP/Programmazione/Variabili
** OperatoriPHP/Programmazione/Operatori
** ArrayPHP/Programmazione/Array
** CondizioniPHP/Programmazione/Condizioni
** CicliPHP/Programmazione/Cicli
** Funzioni di basePHP/Programmazione/Funzioni di base
** Funzioni personalizzatePHP/Programmazione/Funzioni personalizzate
** Variabili globaliPHP/Programmazione/Variabili globali
*** $GLOBALSPHP/Programmazione/Variabili globali/$GLOBALS
*** $_GETPHP/Programmazione/Variabili globali/$_GET
*** $_POSTPHP/Programmazione/Variabili globali/$_POST
*** $_SESSIONPHP/Programmazione/Variabili globali/$_SESSION
*** $_COOKIEPHP/Programmazione/Variabili globali/$_COOKIE
*** $_SERVERPHP/Programmazione/Variabili globali/$_SERVER
** FilePHP/Programmazione/File
** ImmaginiPHP/Programmazione/Immagini
** Espressioni regolariPHP/Programmazione/Regexp
** Programmazione orientata agli oggettiPHP/Programmazione/OOP
* Programmazione avanzata con le classi PEARPHP/PEAR
* PHP e i databasePHP/Database
** Funzioni PHP per l'accesso ai database
*** Funzioni MySQLPHP/Programmazione/MySQL
**** Accesso al databasePHP/Programmazione/MySQL/Accesso al database
**** QueryPHP/Programmazione/MySQL/Query
**** Risultati di una queryPHP/Programmazione/MySQL/Risultati di una query
**** Liberare memoria dai risultati di una queryPHP/Programmazione/MySQL/Liberare memoria dai risultati di una query
**** Chiudi connessione al dbPHP/Programmazione/MySQL/Chiudi connessione al db
*** Funzioni PostgreSQLPHP/PostgreSQL
**** Accesso al database
**** Query
**** Risultati di una query
*** Funzioni Sqlite
**** Accesso al database
**** Query
**** Risultati di una query
** Database e object oriented
*** Abstraction Layers
**** PDO - Php Data Objects
**** PEAR::MDB2
**** Creole
*** Object Relational Mapping (ORM)
**** PEAR:DB_DataObject
**** PEAR:DB_Table
**** Propel
* PHP Design PatternPHP/PHP Design Pattern
* SmartyPHP/Smarty
* Sicurezza delle applicazioni web
* PHP CLI: Command Line InterpreterPHP/Cli
* PHP GTK2: applicazioni desktop in PHPPHP/Gtk
* Crediti
Modifica il sommario
La programmazione object oriented (o programmazione orientata agli oggetti, abbreviata spesso con OOP, object oriented programming) è uno stile, un paradigma di programmazione che consiste nel modellare un problema definendo degli oggetti che interagiscono fra di loro. Un oggetto è un insieme logico costituito da dati e da funzioni che manipolano i dati stessi e creano l'interfaccia tramite la quale l'oggetto interagisce con gli altri oggetti.
In questo capitolo tratteremo di programmazione orientata agli oggetti in PHP 5. Una delle maggiori novità di PHP 5, infatti, è proprio il nuovo object model che rende PHP un linguaggio realmente object oriented (orientato agli oggetti). Queste nuove caratteristiche, che analizzeremo nel prosieguo del capitolo, hanno permesso lo sviluppo di tecniche aderenti ai pattern di progettazione più moderni. Inoltre, come annunciato sul sito ufficiale, PHP 4 è ormai giunto al tramonto e non è più supportato a partire dall'agosto 2008. Pertanto, per quanto riguarda l'object model di PHP 4, rimandiamo alla documentazione ufficiale (in italiano)

## Le classi

Una classe definisce una categoria di oggetti, aventi tutti le stesse caratteristiche. In effetti, il concetto di classe precede quello di oggetto:
* prima penso ad una classe e ne definisco i dati, detti attributi (i quali in realtà sono delle variabili), e le funzioni che li manipolano, dette metodi
* in seguito istanzio un oggetto a partire dalla classe: possiamo pensare alla classe come ad uno "stampino" per creare oggetti e ad un oggetto come ad un'entità "concreta" della classe. Per creare le istanze di ciascun oggetto è comodo utilizzare un costruttore, ovvero una funzione che imposti fin dall'inizio alcuni attributi fondamentali della classe.
Facciamo un esempio mentale. La classe "cane" definisce, nella nostra mente, il miglior amico dell'uomo, con tutte le sue caratteristiche, cioè gli attributi (per es. la razza, il colore del manto). L'oggetto "Lassie" è un'istanza della classe cane in cui l'attributo razza è Collie, il colore del manto è bianco e marrone, ecc....
Per creare una classe in PHP è sufficiente utilizzare la sintassi:
Il costruttore può essere anche una funzione con lo stesso nome della classe.
In questo modo è stata creata una classe NomeClasse. Per crearne una nuova instanza, sarà sufficiente scrivere:
Con questa istruzione creiamo un nuovo oggetto dallo "stampino" NomeClasse; i parametri passati tra parentesi sono quelli richiesti dalla funzione __construct (se prevista). Per accedere agli attributi o ai metodi della classe si userà la sintassi:
Quando si lavora con le classi, la cosa più comoda è creare un file class.NomeClasse.php in cui inserire il codice della classe e poi richiamare tale file negli script in cui si desidera lavorare tramite l'istruzione include_once:
Per accedere all'attributo dall'interno della classe si usa this, per accedervi dall'esterno: "il nome dell'oggetto -> e il nome del metodo":
Come si vede la funzione stampa accede alla variabile privata a tramite la keyword this e ->, si noti il $ la keyword this diventa variabile e prende il $ che non va applicato al nome della variabile privata! Per accedere al metodo stampa usiamo il costrutto: "il nome oggetto -> e il nome metodo". Potremmo accedere anche ad una variabile della classe nello stesso modo (vedi ultima riga):
se invece vogliamo ottenere la variabile privata, il metodo get_var accede per noi alla variabile privata e ne restituisce il valore, che verrà salvato nella variabile $variabile_privata.

## Ereditarietà

Una classe può estenderne un'altra ereditandone così i metodi e gli attributi. La classe estesa si chiama superclasse ed è estesa da una sottoclasse. La sottoclasse può sovrascrivere (overriding, da non confondere con l'overloading) i metodi della superclasse definendone di propri, per estendere una classe è sufficiente, dopo il nome della classe estendente, mettere la parola chiave extends ed il nome della classe da estendere.
Come si vede il metodo visualizza è sovrascritto dalle varie sottoclassi: pere e mele. Bisogna prestare particolare attenzione con gli indicatori di visibilità, come vedremo fra poco.

## Polimorfismo

Nell'esempio sopra abbiamo una chiara dimostrazione di polimorfismo, il metodo visualizza è chiamato più volte ma ogni volta dà un risultato differente a seconda che l'oggetto appartenga ad una od un'altra classe. Se richiamo visualizza con fushi che è un oggetto della classe mele, ecco che visualizzerà "questa è una mela", mentre se lo richiamo con williams. visualizzerà "questa è una pera", il polimorfismo è quindi la capacità di uno stesso metodo di eseguire compiti differenti in base alla classe dell'oggetto di appartenenza, infatti il metodo richiamato è sempre visualizza ma si comporterà in modo diverso a seconda della classe dell'oggetto.

## Ambito

Abbiamo detto che un attributo non è altro che una variabile della classe; bisogna tuttavia fare attenzione all'ambito dell'attributo, ovvero alla visibilità che ha l'attributo dall'esterno.
* public rende l'attributo o il metodo visibile e utilizzabile anche dall'esterno della classe
* protected l'attributo o il metodo possono essere visti/usati solo dall'interno della classe o da una sottoclasse
* private l'attributo o il metodo può essere visto/usato solo all'interno della classe.
Se si usa la dichiarazione deprecata di php<5: var, senza specificare l'ambito dell'attributo, questo avrà come ambito per default pubblico
Se decommentiamo (togliendo i caratteri "//") la riga 21, il motore php restituirà il seguente errore: PHP Fatal error: Cannot access private property prova::$priv in /path_del_file/test.php on line 14, referer: http://localhost/
La stessa cosa succede se ricommentiamo la riga 21 (rimettendo i caratteri "//") decommentiamo la riga 22: questo perché stiamo richiamando la variabile dall'esterno della classe. Come si vede invece dalla riga 25, il metodo stampa viene richiamato dalla variabile a che è istanza della classe prova. Essendo il metodo stampa parte della classe prova, esso può accedere alla variabile privata priv. Decommentando la riga 29 otterremo un effetto che può sembrare particolare, anziché dare errore il motore stamperà b priv e tutto quello che segue questa riga. Infatti la variabile privata priv non viene estesa ed il motore non restituisce un errore fatale, bensì: Undefined property: altro::$priv in /path/test.php on line 29, referer: http://localhost/
La riga 32 mostra che il metodo ristampa può accedere alla variabile protetta prot, infatti tale variabile è estesa alla classe altro.

## Classi astratte

Le classi astratte definiscono delle linee guida per i metodi che le classi che estendono dovranno seguire. Non definiscono il corpo del metodo, bensì il nome, la visibilità, i parametri, cioè quella che viene definita la signature. Il motivo è semplice, si pensi ad un programma sviluppato da più gruppi di sviluppatori, un gruppo definisce la classe madre, mentre gli altri scrivono delle sottoclassi ridefinendo alcuni metodi. Se i gruppi non hanno una buona intercomunicabilità potrebbero ridefinire a piacere i metodi della superclasse cambiando i parametri o la visibilità dello stesso metodo e per evitare ciò esistono le classi astratte.
Se una classe ha anche solo un metodo astratto è obbligatorio definirla come astratta, se una classe eredita da una classe astratta è obbligatorio ridefinirne tutti i metodi astratti. In PHP non è possibile dichiarare un metodo come astratto e definirlo nella stessa classe come permettono alcuni linguaggi OOP.
Una classe o un metodo si dichiarano astratti con la keyword abstract:
Bisogna mantenere inalterata la signature e cioè nome namespace parametri, si può cambiare solo la visibilità, restringendola. Una classe astratta non può essere istanziata direttamente.

## Incapsulamento

Si definisce incapsulamento la tecnica di rendere invisibile ed inaccessibile parti di codice non necessario per l'utilizzo di una classe, rendendo accessibili e visibili solo alcuni metodi e alcuni attributi. Si ottiene grazie agli indicatori di visibilità e alle interfacce.

## Interfacce

Le interfacce sono delle ulteriori astrazioni delle classi astratte. Vengono definite tramite la keyword interface seguita dal nome voluto per l'interfaccia e le graffe.
In pratica è come dichiarare una classe astratta, con l'agevolazione di non dover dichiarare tutto abstract. Una classe che implementi tale interfaccia deve ridefinire tutti i metodi obbligatoriamente pena errore fatale, esattamente come per le classi astratte. Vediamo l'implementazione:
Come per le classi astratte la classe implementante deve ridefinire tutti i metodi, preservando la signature tranne per l'ambito che può essere ristretto.