Skip to content

5. Oggetti

5.1. Qualsiasi variabile può diventare un oggetto con attributi (esempio_14)


<?php
 
// any variable can have attributes by construction
$obj1->attr1 = "un";
$obj1->attr2 = 100;
// displays the
print "objet1=[$obj1->attr1,$obj1->attr2]\n";
// modify object
$obj1->attr2+=100;
// displays the
print "objet1=[$obj1->attr1,$obj1->attr2]\n";
// assigns the value of object1 to object2
$obj2 = $obj1;
// modify obj2
$obj2->attr2 = 0;
// displays both objects
print "objet1=[$obj1->attr1,$obj1->attr2]\n";
print "objet2=[$obj2->attr1,$obj2->attr2]\n";
// assigns the reference from object1 to object3
$obj3 = &$obj1;
// modify obj3
$obj3->attr2 = 10;
// displays both objects
print "objet1=[$obj1->attr1,$obj1->attr2]\n";
print "objet3=[$obj3->attr1,$obj3->attr2]\n";
// is an object a dictionary?
print count($obj1)."\n";
while (list($attribut, $valeur) = each($obj1))
  print "obj1[$attribut]=$valeur\n";
// end
exit;
?>

Risultati:

objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]
objet1=[un,10]
objet3=[un,10]
1
obj1[attr1]=un
obj1[attr2]=10

Commenti

  • riga 4: la notazione $obj->attr si riferisce all'attributo attr della variabile $obj. Se non esiste, viene creato, rendendo così la variabile $obj un oggetto con attributi.
  • Riga 13: l'espressione $obj2 = $obj1, quando $obj1 è un oggetto, costituisce una copia degli oggetti per riferimento. Pertanto, $obj2 e $obj1 sono riferimenti allo stesso oggetto. L'oggetto stesso può essere modificato tramite entrambi i riferimenti.
  • Riga 20: l'espressione $obj3=&$obj1 assegna il riferimento (indirizzo) della variabile $obj1 a $obj3. Se $obj1 è un oggetto, come in questo caso, l'espressione precedente è equivalente a $obj3=$obj1.
  • Righe 28–29: dimostrano che un oggetto può essere attraversato come un dizionario. Le chiavi del dizionario sono i nomi degli attributi e i valori del dizionario sono i valori di quegli stessi attributi.
  • Riga 27: la funzione count può essere applicata a un oggetto ma, contrariamente a quanto ci si potrebbe aspettare, non restituisce il numero di attributi. Pertanto, un oggetto presenta delle somiglianze con un dizionario ma non è un dizionario.

5.2. Una classe Person senza attributi dichiarati (esempio_15)


<?php
 
class Personne {
 
  // class attributes
  // undeclared - can be created dynamically
 
  // method
  function identité() {
    // a priori, uses non-existent attributes
    return "[$this->prénom,$this->nom,$this->âge]";
  }
}
 
// test
// attributes are public and can be created dynamically
$p = new Personne();
$p->prénom = "Paul";
$p->nom = "Langevin";
$p->âge = 48;
// method call
print "personne=" . $p->identité() . "\n";
// end
exit;
?>

Risultati:

personne=[Paul,Langevin,48]

Commenti

  • Righe 3–13: definiscono una classe Person. Una classe è un modello utilizzato per creare oggetti. Una classe è un insieme di attributi e funzioni chiamate metodi. Gli attributi non devono necessariamente essere dichiarati.
  • Righe 9–12: il metodo identity visualizza i valori di tre attributi non dichiarati nella classe. La parola chiave $this si riferisce all'oggetto a cui viene applicato il metodo.
  • Riga 17: viene creato un oggetto $p di tipo Person. La parola chiave new viene utilizzata per creare un nuovo oggetto. L'operazione restituisce un riferimento all'oggetto creato (ovvero un indirizzo). Sono possibili varie notazioni: new Person(), new Person, new person. Il nome della classe non fa distinzione tra maiuscole e minuscole.
  • Righe 18–20: I tre attributi richiesti dal metodo identity vengono creati nell'oggetto $p.
  • Riga 22: il metodo identity della classe Person viene applicato all'oggetto $p. Nel codice (righe 9–11) del metodo identity, $this si riferisce allo stesso oggetto di $p.

5.3. La classe Person con attributi dichiarati (esempio_16)


<?php
 
class Personne {
 
  // class attributes
  var $prénom;
  var $nom;
  var $âge;
 
  // method
  function identité() {
    return "[$this->prénom,$this->nom,$this->âge]";
  }
}
// test
// attributes are public
$p = new Personne();
$p->prénom = "Paul";
$p->nom = "Langevin";
$p->âge = 48;
// method call
print "personne=" . $p->identité() . "\n";
// end
exit;
?>

Risultati:

personne=[Paul,Langevin,48]

Commenti

  • righe 6–8: gli attributi della classe sono dichiarati esplicitamente utilizzando la parola chiave var.

5.4. La classe Person con un costruttore (esempio_17)

Gli esempi precedenti mostravano classi Person poco convenzionali, come quelle che si potevano trovare in PHP 4. Non è consigliabile seguire questi esempi. Presentiamo ora una classe Person che segue le migliori pratiche di PHP 5:


<?php
 
class Personne {
 
// class attributes
  private $prénom;
  private $nom;
  private $âge;
 
// getters and setters
  public function getPrénom() {
    return $this->prénom;
  }
 
  public function getNom() {
    return $this->nom;
  }
 
  public function getAge() {
    return $this->âge;
  }
 
  public function setPrénom($prénom) {
    $this->prénom = $prénom;
  }
 
  public function setNom($nom) {
    $this->nom = $nom;
  }
 
  public function setAge($age) {
    $this->âge = $age;
  }
 
// manufacturer
  function __construct($prénom, $nom, $âge) {
    // we go through sets
    $this->setPrénom($prénom);
    $this->setNom($nom);
    $this->setAge($âge);
  }
 
// method toString
  function __toString() {
    return "[$this->prénom,$this->nom,$this->âge]";
  }
 
}
 
// test
// creation of a person object
$p = new Personne("Paul", "Langevin", 48);
// identity of this person
print "personne=$p\n";
// we change the age
$p->setAge(14);
// identity of the person
print "personne=$p\n";
// end
exit;
?>

Risultati:

personne=[Paul,Langevin,48]
personne=[Paul,Langevin,14]

Commenti

  • righe 3-48: la classe Person
  • righe 6-8: gli attributi privati della classe. Questi attributi sono visibili solo all'interno della classe. Altre parole chiave che possono essere utilizzate sono:
  • public: rende l'attributo un attributo pubblico visibile dall'esterno della classe
  • protected: rende l'attributo un attributo protetto, visibile dall'interno della classe e delle sue classi derivate.
  • Poiché gli attributi sono privati, non è possibile accedervi dall'esterno della classe. Pertanto, non è possibile scrivere il seguente codice:
$p=new Personne() ;
$p->nom="Landru" ;

Qui ci troviamo al di fuori della classe Person. Poiché l'attributo name è privato, la riga 2 è errata. Per inizializzare i campi privati dell'oggetto $p, ci sono due modi:

  • (continua)
    • utilizzare i metodi pubblici set e get (i nomi di questi metodi possono essere qualsiasi cosa) dalle righe 11–33. Possiamo quindi scrivere:
$p=new Personne() ;
$p->setNom("Landru") ;
  • (continua)
    • Utilizza il costruttore delle righe 36–41. Scriveremmo quindi:
$p=new Personne("Michel","Landru",44) ;

Il codice sopra riportato richiama automaticamente il metodo della classe Person denominato __construct.

  • Riga 54: Questa riga visualizza l'oggetto Person $p come stringa. Per farlo, viene utilizzato il metodo della classe Person denominato __toString.

5.5. La classe Person con controlli di validità nel costruttore (esempio_18)

Il costruttore di una classe è il posto giusto per verificare che i valori di inizializzazione dell'oggetto siano corretti. Tuttavia, un oggetto può anche essere inizializzato tramite i suoi metodi set o equivalenti. Per evitare di duplicare gli stessi controlli in due posti diversi, li inseriremo all'interno dei metodi set. Se il valore di inizializzazione di un oggetto risulta errato, verrà generata un'eccezione. Ecco un esempio:


<?php
 
class Personne {
 
// class attributes
  private $prénom;
  private $nom;
  private $âge;
 
// getters and setters
  public function getPrénom() {
    return $this->prénom;
  }
 
  public function getNom() {
    return $this->nom;
  }
 
  public function getAge() {
    return $this->âge;
  }
 
  public function setPrénom($prénom) {
    // first name must be non-empty
    if (!preg_match("/^\s*(.+?)\s*$/", $prénom, $champs)) {
      throw new Exception("Le prénom doit être non vide");
    } else {
      $this->prénom = $champs[1];
    }
  }
 
  public function setNom($nom) {
    // name must be non-empty
    if (!preg_match("/^\s*(.+?)\s*$/", $nom, $champs)) {
      throw new Exception("Le nom doit être non vide");
    } else {
      $this->nom = $champs[1];
    }
  }
 
  public function setAge($âge) {
    // age must be valid
    if (!preg_match("/^\s*(\d+)\s*$/", $âge, $champs)) {
      throw new Exception("L'âge doit être un entier positif ou nul");
    } else {
      $this->âge = $champs[1];
    }
  }
 
// manufacturer
  function __construct($prénom, $nom, $âge) {
    // we go through sets
    $this->setPrénom($prénom);
    $this->setNom($nom);
    $this->setAge($âge);
  }
 
  // method toString
  function __toString() {
    return "[$this->prénom,$this->nom,$this->âge]";
  }
}
 
// test
// creation of a Personne object
$p = new Personne("Paul", "Langevin", 48);
// identity of this person
print "personne=$p\n";
// creation of an erroneous Person object
try {
  $p = new Personne("xx", "yy", "zz");
} catch (Exception $e) {
  print $e->getMessage();
}
// end
exit;
?>

Risultati:

personne=[Paul,Langevin,48]
L'âge doit être un entier positif ou nul

Commenti

  • righe 23-30: inizializzazione dell'attributo first_name e verifica del valore di inizializzazione
  • riga 25: uso di un'espressione regolare. Il nome è una sequenza di uno o più caratteri, eventualmente preceduta o seguita da spazi.
  • riga 26: se il cognome è vuoto, viene generata un'eccezione; altrimenti, il nome viene memorizzato (riga 28)
  • riga 66: uso del costruttore della classe Person
  • riga 68: uso del metodo __toString della classe Person
  • Righe 70–74: gestione di eventuali eccezioni generate dal costruttore della classe Person.

5.6. Aggiunta di un metodo che funge da secondo costruttore (esempio_19)

In PHP 5 non è possibile avere più costruttori con parametri diversi che consentano di costruire un oggetto in vari modi. Possiamo quindi utilizzare metodi che fungono da costruttori:


<?php
 
class Personne {
 
// class attributes
  private $prénom;
  private $nom;
  private $âge;
 
// getters and setters
  public function getPrénom() {
    return $this->prénom;
  }
 
….
 
// manufacturer
  function __construct($prénom, $nom, $âge) {
    // we go through sets
    $this->setPrénom($prénom);
    $this->setNom($nom);
    $this->setAge($âge);
  }
 
  // method
  public function initWithPersonne($p) {
    // initializes the current object with a person $p
    $this->__construct($p->prénom, $p->nom, $p->âge);
  }
 
  // method toString
  function __toString() {
    return "[$this->prénom,$this->nom,$this->âge]";
  }
 
}
 
// test
// creation of a Personne object
$p = new Personne("Paul", "Langevin", 48);
// identity of this person
print "personne=$p\n";
// creation of a second person
$p2 = new Personne("Laure", "Adeline", 67);
// initialization of the first with the values of the second
$p->initWithPersonne($p2);
// check
print "personne=$p\n";
// end
exit;
?>

Risultati:

personne=[Paul,Langevin,48]
personne=[Laure,Adeline,67]

Commenti

  • righe 26-29: Il metodo initWithPerson consente di assegnare i valori degli attributi di un altro oggetto Person all'oggetto corrente. Qui, chiama il costruttore __construct, ma ciò non è obbligatorio.

5.7. Un array di oggetti Person (esempio_20)

L'esempio seguente mostra che è possibile avere array di oggetti.


<?php
 
class Personne {
 
// class attributes
  private $prénom;
  private $nom;
  private $âge;
 
// getters and setters
  public function getPrénom() {
    return $this->prénom;
  }
 
...
 
// manufacturer
  function __construct($prénom, $nom, $âge) {
    // we go through sets
    $this->setPrénom($prénom);
    $this->setNom($nom);
    $this->setAge($âge);
  }
 
  // method
  public function initWithPersonne($p) {
….
  }
 
  // method toString
  function __toString() {
    ...
  }
 
}
 
// test
// create an array of Personne objects
$groupe = array(new Personne("Paul", "Langevin", 48), new Personne("Sylvie", "Lefur", 70));
 
// identity of these persons
for ($i = 0; $i < count($groupe); $i++)
  print "groupe[$i]=$groupe[$i]\n";
// end
exit;
?>

Risultati:

groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]

Commenti

  • riga 39: creazione di un array di 2 persone
  • riga 42: iterazione sull'array
  • riga 43: $group[$i] è un oggetto di tipo Person. Il metodo __toString viene utilizzato per visualizzarlo.

5.8. Creazione di una classe derivata dalla classe Person (esempio_21)


<?php
 
class Personne {
 
// class attributes
  private $prénom;
  private $nom;
  private $âge;
 
// getters and setters
  public function getPrénom() {
    return $this->prénom;
  }
...
 
// manufacturer
  function __construct($prénom, $nom, $âge) {
    // we go through sets
    $this->setPrénom($prénom);
    $this->setNom($nom);
    $this->setAge($âge);
  }
 
  // method
  public function initWithPersonne($p) {
    // initializes the current object with a person $p
    $this->__construct($p->prénom, $p->nom, $p->âge);
  }
 
  // method toString
  function __toString() {
    return "[$this->prénom,$this->nom,$this->âge]";
  }
 
}
 
// a class derived from Personne
class Enseignant extends Personne {
 
  // attributes
  private $discipline;   // d// subject taught
 
  // getter and setter
 
  public function getDiscipline() {
    return $this->discipline;
  }
 
  public function setDiscipline($discipline) {
    $this->discipline = $discipline;
  }
 
  // manufacturer
 
  public function __construct($prénom, $nom, $âge, $discipline) {
    // parent attributes
    parent::__construct($prénom, $nom, $âge);
    // other attributes
    $this->setDiscipline($discipline);
  }
 
  // overloads the __toString function of the parent class
  public function __toString() {
    return "[" . parent::__toString() . ",$this->discipline]";
  }
 
}
 
// test
// creation of an array of Personne and derived objects
$groupe = array(new Enseignant("Paul", "Langevin", 48, "anglais"), new Personne("Sylvie", "Lefur", 70));
 
// identity of these persons
for ($i = 0; $i < count($groupe); $i++)
  print "groupe[$i]=$groupe[$i]\n";
// end
exit;
?>

Risultati:

groupe[0]=[[Paul,Langevin,48],anglais]
groupe[1]=[Sylvie,Lefur,70]

Commenti

  • righe 3-35: la classe Person
  • riga 38: la classe Teacher estende la classe Person. La classe derivata Teacher eredita gli attributi e i metodi della sua classe padre.
  • riga 41: la classe Teacher aggiunge un nuovo attributo, subject, che è specifico di essa
  • riga 55: il costruttore della classe Teacher accetta 4 parametri
    • 3 per inizializzare la sua classe padre (first_name, last_name, age)
    • 1 per la propria inizializzazione (subject)
  • riga 57: la classe derivata ha accesso ai metodi e ai costruttori della sua classe padre tramite la parola chiave parent::. Qui, passiamo i parametri (first_name, last_name, age) al costruttore della classe padre.
  • riga 64: il metodo __toString della classe derivata utilizza il metodo __toString della classe padre.
  • riga 71: un array contenente un oggetto Teacher e un oggetto Person.
  • riga 74: percorriamo gli elementi dell'array
  • riga 75: verrà chiamato il metodo __toString di ciascun elemento $group[$i]. La classe Person dispone di un metodo __toString. La classe Teacher ne ha due: quello della classe padre e il proprio. Ci si potrebbe chiedere quale dei due verrà chiamato. L'esecuzione mostra che è stato chiamato il metodo della classe Teacher. È sempre così: quando viene chiamato un metodo su un oggetto, viene cercato nel seguente ordine: nell'oggetto stesso, nella sua classe padre se ne ha una, poi nella classe padre della classe padre, e così via... La ricerca si interrompe non appena viene trovato il metodo.

5.9. Creazione di una seconda classe derivata dalla classe Person (esempio_22)

L'esempio seguente crea una classe Student derivata dalla classe Person:


<?php
 
class Personne {
 
// class attributes
  private $prénom;
  private $nom;
  private $âge;
 
// getters and setters
  public function getPrénom() {
    return $this->prénom;
  }
...
 
// manufacturer
  function __construct($prénom, $nom, $âge) {
    // we go through sets
    $this->setPrénom($prénom);
    $this->setNom($nom);
    $this->setAge($âge);
  }
 
  // method
  public function initWithPersonne($p) {
    // initializes the current object with a person $p
    ...
  }
 
  // method toString
  function __toString() {
    return "[$this->prénom,$this->nom,$this->âge]";
  }
 
}
 
// a class derived from personne
class Enseignant extends Personne {
 
  // attributes
  private $discipline;   // d// subject taught
 
  // getter and setter
...
 
  // manufacturer
 
  public function __construct($prénom, $nom, $âge, $discipline) {
    // parent attributes
    parent::__construct($prénom, $nom, $âge);
    // other attributes
    $this->setDiscipline($discipline);
  }
 
  // overloads the _identité__toString function of the parent class
  public function __toString() {
    return "[" . parent::__toString() . ",$this->discipline]";
  }
 
}
 
// a class derived from Personne
class Etudiant extends Personne {
 
  // attributes
  private $formation;   // d// subject taught
 
  // getter and setter
 
  public function getFormation() {
    return $this->formation;
  }
 
  public function setFormation($formation) {
    $this->formation = $formation;
  }
 
  // manufacturer
 
  public function __construct($prénom, $nom, $âge, $formation) {
    // parent attributes
    parent::__construct($prénom, $nom, $âge);
    // other attributes
    $this->setFormation($formation);
  }
 
  // overloads the __toString function of the parent class
  public function __toString() {
    return "[" . parent::__toString() . ",$this->formation]";
  }
 
}
 
// test
// creation of a table of person objects and derivatives
$groupe = array(new Enseignant("Paul", "Langevin", 48, "anglais"), new Personne("Sylvie", "Lefur", 70), new Etudiant("Steve", "Boer", 23, "iup2 qualité"));
 
// identity of these persons
for ($i = 0; $i < count($groupe); $i++)
  print "groupe[$i]=$groupe[$i]\n";
// end
exit;
?>

Risultati:

groupe[0]=[[Paul,Langevin,48],anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[[Steve,Boer,23],iup2 qualité]

5.10. Interfacce (esempio_23)

Un'interfaccia è una struttura che definisce i prototipi dei metodi. Una classe che implementa un'interfaccia definisce il codice per tutti i metodi dell'interfaccia.


<?php
 
// an interface
interface IExemple {
  function ajouter($i, $j);
 
  function soustraire($i, $j);
}
 
// interface implementation 1
class Classe1 implements IExemple {
 
  public function ajouter($a, $b) {
    return $a + $b + 10;
  }
 
  public function soustraire($a, $b) {
    return $a - $b + 20;
  }
 
}
 
// interface implementation 2
class Classe2 implements IExemple {
 
  public function ajouter($a, $b) {
    return $a + $b + 100;
  }
 
  public function soustraire($a, $b) {
    return $a - $b + 200;
  }
 
}
 
// function
function calculer($a, $b, IExemple $interface) {
  print $interface->ajouter($a, $b)."\n";
  print $interface->soustraire($a, $b)."\n";
}
 
// ------------------- hand
// creation of 2 objects of type Class1 and Class2
$c1 = new Classe1();
$c2 = new Classe2();
// call the calculate function
calculer(4, 3, $c1);
calculer(14, 13, $c2);
?>

Risultati

17
21
127
201

Commenti

  • Righe 4–8: L'interfaccia IExample definisce due metodi: la funzione add (riga 5) e la funzione subtract (riga 7). L'interfaccia non definisce il codice per questi metodi. Saranno le classi che implementano l'interfaccia a farlo.
  • Riga 11: La classe Class1 implementa l'interfaccia IExample. Definisce quindi il codice per il metodo add (riga 13) e il metodo subtract (riga 17).
  • Righe 24–34: Lo stesso vale per la classe Class2.
  • Riga 37: Il metodo *calculer accetta tre parametri: due interi, *$a* e $b*, e un oggetto *$interface che implementa l'interfaccia *IExemple. Avremmo potuto scrivere function calculate($a, $b, $interface) senza specificare il tipo IExample del parametro *$interface*. Specificandolo, permettiamo all'interprete PHP di verificare che il parametro effettivo sia effettivamente un oggetto che implementa l'interfaccia *IExample*.
  • Righe 38–39: utilizzo dei metodi add e subtract dell'oggetto $interface. Poiché implementa l'interfaccia IExample, sappiamo che dispone di questi due metodi.
  • Righe 44–45: creazione di due oggetti di tipi diversi, entrambi implementanti l'interfaccia IExample.
  • Riga 47: passiamo l'oggetto $c1 di tipo Class1, che implementa l'interfaccia IExample, alla funzione calculate.
  • Riga 48: l'oggetto $c2 di tipo Class2, che implementa l'interfaccia IExample, viene passato alla funzione calculate.