Per offrirti un'esperienza di navigazione sempre migliore, questo sito utilizza cookie propri e di terze parti, partner selezionati. I cookie di terze parti potranno anche essere di profilazione.
Le tue preferenze si applicheranno solo a questo sito web. Puoi modificare le tue preferenze in qualsiasi momento ritornando su questo sito o consultando la nostra informativa sulla riservatezza.
E' possibile rivedere la nostra privacy policy cliccando qui e la nostra cookie policy cliccando qui.
Per modificare le impostazioni dei cookies clicca qui
  • seguici su feed rss
  • seguici su twitter
  • seguici su linkedin
  • seguici su facebook
  • cerca

SEI GIA' REGISTRATO? EFFETTUA ADESSO IL LOGIN.



ricordami per 365 giorni

HAI DIMENTICATO LA PASSWORD? CLICCA QUI

NON SEI ANCORA REGISTRATO ? CLICCA QUI E REGISTRATI !

Le classi in PHP. introduzione alla programmazione in stile OOP, metodi e proprietà di una classe.

di :: 26 ottobre 2020
Le classi in PHP. introduzione alla programmazione in stile OOP, metodi e proprietà di una classe.

A partire dalla versione 5, PHP, dopo essere stato solo un linguaggio procedurale, si è affacciato alla programmazione ad oggetti, introducendo le classi.

E' una significativa evoluzione di PHP, ed oggi possiamo tranquillamente paragonarlo ad altri più affermati linguaggi che lavorano ad oggetti come ad esempio JAVA, anche se PHP è per sua natura solo "web oriented" e quindi presenta limiti sia nell’architettura che nella sintassi. Per questo motivo spesso si parla di "programmazione in stile OOP" e non proprio di "Programmazione Orientata agli Oggetti".

Alla base di questa "Programmazione Orientata agli Oggetti" vi sono le classi.

Nel PHP procedurale siamo abituati a lavorare solo con le funzioni, ed all'interno delle funzioni eseguiamo una serie di operazioni.

In estrema sintesi possiamo dire, a chi non sa cosa siano le classi, e me ne vogliamo i programmatori skillati, che le classi sono dei contenitori, al cui interno ci sono variabili e funzioni. Non andrò più a chiamare direttamente una funzione, bensi chiamerò inizialmente la classe, ed in termine tecnico si dice cha vado a "istanziare un oggetto di quella classe", e grazie a questa istanza posso poi accedere alle variabili e alle funzioni contenute dentro la classe. Quindi c'è uno step in più rispetto all'utilizzo classico delle funzioni: la creazione di un oggetto di quella classe. Creato l'oggetto posso utilizzare la funzione in essa contenuta.

Inoltre all'interno di una classe:

  • le variabili si chiamano proprietà
  • le funzioni si chiamano metodi

Voi potrete pensare che questa sia una complicazione. Potrei forse essere d'accordo con voi per progetti di piccola entità o se lavorate da soli. Ma se avete a che fare con progetti elaborati ed al progetto collaborano più persone, questo tipo di approccio risulterà senza dubbio migliore per l'organizzazione del codice, per il suo riutilizzo, per la possibilità di lavorare assieme ad altri programmatori su blocchi di codici separati, e per tutta una serie di ragioni che scoprirete da soli utilizzandolo.

Struttura di una classe

Per definire una classe nel nostro script PHP utilizziamo la parola chiave "class" seguita da un nome a nostra scelta, e non deve contenere spazi.

Per convenzione si utilizza la prima lettera maiuscola, e nel caso questo nome contenga più parole, in maiuscolo la prima lettera di ogni parola.

Dopo avere indicato il nome della classe, all'interno di parentesi graffe inseriremo le proprietà e i metodi della classe stessa.

Ecco un esempio molto semplice in cui inseriamo un metodo (una funzione) all'interno della classe "MioTest"

<?php 
class MioTest
{
    public function saluto(){
       echo "ciao";
    }
}
?>

Per adesso non badate a quel "public" messo prima del metodo (funzione), ce ne occuperemo tra poco.

Come si utilizza questa classe?

La prima cosa da fare è "creare un oggetto di classe MioTest" (una istanza della classe), in pratica creo una sorta di connettore a questa classe che poi mi consentirà di chiamare la funzione che è al suo interno.

Per fare questo si utilizza la parola chiave "new" seguita dal nome della classe

$obj = new MioTest;​

Creato l'oggetto $obj posso finalmente accedere alla funzione "saluto" contenuta al suo interno, utilizzando una freccia seguita dal nome della funzione

$obj -> saluto();

Mettiamo tutto assieme nel seguente codice

<?php 
class MioTest
{
    public function saluto(){
       echo "ciao";
    }
}

// creo un oggetto di classe "MioTest"
$obj= new MioTest;
// accedo alla funzione "saluto"
$obj -> saluto();
?>

Lanciate lo script e l'output sarà

ciao

Avete creato la vostra prima classe!

Abbiamo parlato anche di proprietà, cioè delle variabili contenute all'interno di questo microcosmo chiamato classe.

Ampliamo il nostro esempio, inserendo una proprietà (variabile) chiamata "nome" all'interno della classe "MioTest".

<?php 
class MioTest
{
    // proprietà, cioè una variabile
    public $nome="pippo";

    // metodo, cioè una funzione
    public function saluto(){
       echo "ciao da ".$this->nome;
    }
}

// creo un oggetto di classe "MioTest"
$obj= new MioTest;
// accedo alla funzione "saluto"
$obj -> saluto();
?>

Anche in questo caso, per adesso non badate al public presente prima della proprietà.

All'interno nel metodo "saluto" abbiamo utilizzato la proprietò "nome" utilizzando una freccia

$this->nome;

in modo simile a "$obj -> saluto", ma in questo caso siamo dentro la classe e qui dentro si utilzza "$this".

Questo, detto in parole molto semplici.

Visibilità di metodi e proprietà

Abbiamo visto negli esempi precedenti quel "public" anteposto al nome del metodo e della proprietà.

Questa è la visibilità del metodo e della proprietà, e descrive la possibilità di accedere, a questo metodo o proprietà, dall'esterno della classe, e dall'interno.

La visibilità può essere:

  • public: significa che sono accessibili anche da fuori della classe
  • protected: accessibili sono dall'interno della classe
  • private: accessibili sono dall'interno della classe, ma non nelle classi CHILD

Cerchiamo di capire questo concetto ripartendo dall'esempio precedente.

Visilbilità PUBLIC di metodi e proprietà

Il metodo "saluto" ha visibilità public, per cui posso accedere al metodo dall'esterno della classe, ed è quello che abbiamo fatto quando, dopo aver creare l'oggetto di classe "MioTest" abbiamo chiamato il metodo "saluto" così

$obj -> saluto();

Se quel metodo fosse stato "private" o "protected", non avremmo potuto farlo. A titolo di esempio prova a impostare come "private" quel metodo, e rilancia lo script. Il risultato sarà il seguente:

Fatal error: Uncaught Error: Call to private method MioTest::saluto() ....

Rimettete il metodo come pubblico e soffermiamo adesso sulle proprietà (le variabili).

Se la proprietà ha visibilità pubblica, posso utilizzarla dentro e fuori la classe. Dentro, abbiamo già visto come. Fuori lo vediamo adesso e lo facciamo in modo analogo a quando fatto per accedere al metodo, con la freccia:

<?php 
class MioTest
{
    // proprietà, cioè una variabile
    public $nome="pippo";

    // metodo, cioè una funzione
    public function saluto(){
       echo "ciao da ".$this->nome;
    }
}

// creo un oggetto di classe "MioTest"
$obj= new MioTest;
// accedo alla funzione "saluto"
$obj -> saluto();
echo "<br>";
// accedo alla proprietà pubblica $nome
echo $obj -> nome;
?>

L'ouput sarà

ciao da pippo
pippo

Non solo posso utilizzarlo da fuori, ma possiamo anche modificarlo, assegnandogli un valore diverso, in questo modo

<?php 
class MioTest
{
    // proprietà, cioè una variabile
    public $nome="pippo";

    // metodo, cioè una funzione
    public function saluto(){
       echo "ciao da ".$this->nome;
    }
}

// creo un oggetto di classe "MioTest"
$obj= new MioTest;
// assegno alla proprietà "nome" il valore "pluto"
$obj -> nome="pluto";
// accedo alla funzione "saluto"
$obj -> saluto();
?>

L'output sarà

ciao da pluto

Se la proprietà fosse private o protected, non potrei ne accedere ne modificare la proprietà dall'esterno della classe.

Visilbilità PROTECTED di metodi e proprietà

Come abbiamo già detto, una visibilità protected consente di usare metodi e proprietà solo all'interno della classe.

Modifichiamo il nostro esempio così, assegnando visibilità protected alla proprietà "nome". Possiamo tranquillamente continuare ad utilizzarlo nella classe, ma non da fuori.

<?php 
class MioTest
{
    // proprietà, cioè una variabile
    protected $nome="pippo";

    // metodo, cioè una funzione
    public function saluto(){
       echo "ciao da ".$this->nome;
    }
}

// creo un oggetto di classe "MioTest"
$obj= new MioTest;
// accedo alla funzione "saluto"
$obj -> saluto();
?>

Visilbilità PRIVATE di metodi e proprietà

Simili ai precedenti, MA non sono accessibili dalle classi "child", ma per spiegare cosa sono le classi "child" dobbiamo introdurre il concetto di ereditarietà delle classi, e lo facciamo subito

Ereditarietà delle classi

Una classe detta "figlia" o "child" può ereditare proprietà e metodi di un'altra classe "padre" o "parent".

Capiamo subito questo concetto con un esempio. Abbiamo una classe A con dentro tre prorietà (public, private e protected) e tre metodi (public, private e protected) così possiamo vedere in azione tutte le possibilità visibilità

class A {
    // proprietà
    public $isPropPub=1;
    private $isPropPriv=2;
    protected $isPropProt=3;

    // metodi
    public function isMetPub(){
        echo "Metodo".__METHOD."<br />";
    }
    private function isMetPriv(){
        echo "Metodo".__METHOD."<br />";
    }
    protected function isMetProt(){
        echo "Metodo".__METHOD."<br />";
    }
}

Abbiamo poi una seconda classe chiamata "B" che estende la classe "A", utilizzando la parola chiave "extend": è come se fosse un'appendice: al suo interno avrà i suoi metodi e proprietà, ma, estendendo la classe "A" potrà utilizzare (cioè eredita) anche i metodi e proprietà di questa. La classe "B" è la classe "child", la classe "A" è la classe parent.

Nella classe B posso accedere alle proprietà e metodi della classe padre A... ma non a tutti, solo a quelli "public" e a quelli "protected", non a quelli "private" perchè, per quando abbiamo detto prima, sono accessibili solo dall'interno della classe padre A. In questo esempio, nella classe B, ho un metodo pubblico "test" al cui interno accedo alla proprietà "isPropPub" della classe A.

class B extends A {
	public function test() {
	       echo "Ciao dalla classe B: il valore della proprieta isPropPub è ".$this->isPropPub."<br />";
	}
}

In modo analogo avrei potuto accedere alla proprietà "isPropProt" che è protected, e ai metodi pubblici e protetti "isMetPriv()" e "isMetProt()".

Mettiamo assieme tutto il codice, e creiamo un oggetto di classe A ed accediamo come già sappiamo al suo metodo pubblico "isMetPub()". Poi creiamo un oggetto di classe B, e accediamo al suo metodo pubblico "test". Questo, a sua volta, come vediamo lanciando lo script, può accedere ai metodi e proprietà della classe A, e nello spacifico accete alla proprietà "isPropPub"

<?php

class A {
    // proprietà
    public $isPropPub=1;
    private $isPropPriv=2;
    protected $isPropProt=3;

    // metodi
    public function isMetPub(){
        echo "Sto usando il metodo isMetPub della classe A<br />";
    }
    private function isMetPriv(){
        echo "Sto usando il metodo isMetPriv della classe A<br />";
    }
    protected function isMetProt(){
        echo "Sto usando il metodo isMetProt della classe A<br />";
    }
}

class B extends A {
	public function test() {
	       echo "Sto usando la classe B, il valore della proprieta isPropPub è ".$this->isPropPub;
	}
}

// istanzio un oggetto di classe A
$obj = new A;
// accedo al metodo pubblico della classe A "isMetPub"
$obj -> isMetPub();

// istanzio un oggetto di classe B
$obj = new B;
// accedo al metodo test della classe B "test"
$obj -> test();
?>

Il risultato sarà questo

Sto usando il metodo isMetPub della classe A
Sto usando la classe B, il valore della proprieta isPropPub è 1

Lascio a voi fare delle prove di accesso ai vari metodi e proprietà, dall'interno e dall'esterno delle classi.

Esiste un limite all'ereditarietà: PHP non supporta l'ereditarietà multilpla, cioè una classe non può ereditare più classi

class B extends A,C {....}

Ma è possibile superare questo limite con i TRAIT, argomento che tratteremo in un altro articolo.

Override dei metodi e final OOP

Fare un override di un metodo signfica sovrascrivere all'interno della classe figlia un metodo definito all'interno della classe parent

Come esempio, definiamo una classe "F" con dentro un metodo public "test"

class F {
  public function test()
  {
      echo "ciao dalla classe ".__CLASS__;
   }
}

Definiamo anche una classe G che estende la classe "F", con dentro un metodo public con lo stesso nome "test"

class G extends F {
   public function test()
   {
      echo " e qui siamo nella classe ".__CLASS__;
   }
}

Istanziamo uno oggetto della classe figlia "G", e chiamiamo il metodo test

$obj=new G;
$obj->test();

Mettiamo tutto assieme in uno script

<?php

class F {
  public function test()
  {
      echo "ciao dalla classe ".__CLASS__;
   }
}

class G extends F {
   public function test()
   {
      echo " e qui siamo nella classe ".__CLASS__;
   }
}

$obj=new G;
$obj->test();
?>

Lanciamo lo script e verrà richiamato il metodo "test" del CHILD e non del PARENT.

Ma attenzione: il metodo della classe CHILD deve avere visibilità uguale o superiore a quella del PARENT !

L'ordine di importanza di visibilità è il seguente, da quella superiore a quella inferiore:

  1. PUBLIC
  2. PROTECTED
  3. PRIVATE

Per cui:

  • se la classe CHILD avesse un metodo PROTECTED, lo script andrebbe in errore perchè il metodo del PARENT avrebbe visibilità maggiore (PUBLIC) rispoetto alla visibiltià del CHILD (PROTECTED)
  • se nella classe PARENT il metodo fosse stato PROTECTED, la classe CHILD poteva avere un metodo PUBLIC o PROTECTED

C'è anche modo che una classe non venga mai estesa. Per fare questo indichiamo la classe come "final".

final class F {
  public function test()
  {
      echo "ciao dalla classe ".__CLASS__;
   }
}

Prova a modificare con "finale" il tuo script e rilancialo, vedrai questo errore

Fatal error: Class G may not inherit from final class (F) in /var/www/html/test/index.php on line 15

Questo perchè la class "G" estende la "F" ma la classe F non si può estendere !

E' possibile impostare come "finale" una classe, come abbiamo visto, o un metodo.

Se impostiamo come "final" il metodo, la classe potrà essere estesa, è solo il metodo che non potrà essere sovrascritto
Se impostiamo come "final" la classe è tutta la classe a non poter essere estesa.

Update 18/11/2022: ho dedicato un nuovo articolo al come estendere una classe in PHP e all'ereditarietà, con nuovi esempi.

Conclusioni

Abbiamo così terminato questo primo approccio alle classi e alla programmazione orientata agli oggetti in PHP.

Seguiranno altri articoli in cui tratterò di aspetti collegati alle classi come le proprietà e i metodi statici, le costanti, i trait, i namespace, i metodi magici tra cui il metodo costruttore, le classi astratte e le interfacce.

Stay tuned!

Potrebbe interessarti

 
 
 
 
pay per script

Hai bisogno di uno script PHP personalizzato, di una particolare configurazione su Linux, di una gestione dei tuoi server Linux, o di una consulenza per il tuo progetto?

x

ATTENZIONE