Skip to content

5. Objetos

5.1. Qualquer variável pode tornar-se um objeto com atributos (exemplo_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;
?>

Resultados:

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

Comentários

  • linha 4: a notação $obj->attr refere-se ao atributo attr da variável $obj. Se não existir, é criado, tornando assim a variável $obj um objeto com atributos.
  • linha 13: a expressão $obj2 = $obj1, quando $obj1 é um objeto, constitui uma cópia de objetos por referência. Assim, $obj2 e $obj1 são referências ao mesmo objeto. O próprio objeto pode ser modificado por qualquer uma das referências.
  • Linha 20: A expressão $obj3=&$obj1 atribui a referência (endereço) da variável $obj1 a $obj3. Se $obj1 for um objeto, como é o caso aqui, a expressão anterior é equivalente a $obj3=$obj1.
  • Linhas 28–29: demonstram que um objeto pode ser percorrido como um dicionário. As chaves do dicionário são os nomes dos atributos, e os valores do dicionário são os valores desses mesmos atributos.
  • Linha 27: A função count pode ser aplicada a um objeto, mas não retorna, como seria de esperar, o número de atributos. Portanto, um objeto partilha semelhanças com um dicionário, mas não é um.

5.2. Uma classe Pessoa sem atributos declarados (exemplo_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;
?>

Resultados:

personne=[Paul,Langevin,48]

Comentários

  • linhas 3–13: definem uma classe Person. Uma classe é um modelo utilizado para criar objetos. Uma classe é um conjunto de atributos e funções denominadas métodos. Os atributos não têm de ser declarados.
  • Linhas 9–12: O método identity exibe os valores de três atributos não declarados na classe. A palavra-chave $this refere-se ao objeto ao qual o método é aplicado.
  • Linha 17: É criado um objeto $p do tipo Pessoa. A palavra-chave new é utilizada para criar um novo objeto. A operação devolve uma referência ao objeto criado (ou seja, um endereço). São possíveis várias notações: new Pessoa(), new Pessoa, new pessoa. O nome da classe não distingue maiúsculas de minúsculas.
  • Linhas 18–20: Os três atributos exigidos pelo método identity são criados no objeto $p.
  • Linha 22: o método identity da classe Person é aplicado ao objeto $p. No código (linhas 9–11) do método identity, $this refere-se ao mesmo objeto que $p.

5.3. A classe Person com atributos declarados (exemplo_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;
?>

Resultados:

personne=[Paul,Langevin,48]

Comentários

  • linhas 6–8: os atributos da classe são declarados explicitamente utilizando a palavra-chave var.

5.4. A classe Pessoa com um construtor (exemplo_17)

Os exemplos anteriores mostraram classes Person pouco comuns, tal como poderiam ter sido encontradas no PHP 4. Não é recomendável seguir estes exemplos. Apresentamos agora uma classe Person que segue as melhores práticas do 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;
?>

Resultados:

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

Comentários

  • linhas 3-48: a classe Pessoa
  • linhas 6-8: os atributos privados da classe. Estes atributos só são visíveis dentro da classe. Outras palavras-chave que podem ser utilizadas são:
  • public: torna o atributo um atributo público, visível a partir do exterior da classe
  • protected: torna o atributo um atributo protegido, visível de dentro da classe e das suas classes derivadas.
  • Como os atributos são privados, não podem ser acedidos a partir do exterior da classe. Por conseguinte, não podemos escrever o seguinte código:
$p=new Personne() ;
$p->nom="Landru" ;

Aqui, estamos fora da classe Person. Como o atributo name é privado, a linha 2 está incorreta. Para inicializar os campos privados do objeto $p, existem duas maneiras:

  • (continuação)
    • utilizar os métodos públicos set e get (os nomes destes métodos podem ser quaisquer) das linhas 11–33. Podemos então escrever:
$p=new Personne() ;
$p->setNom("Landru") ;
  • (continuação)
    • Utilize o construtor das linhas 36–41. Escreveríamos então:
$p=new Personne("Michel","Landru",44) ;

O código acima chama automaticamente o método da classe Person chamado __construct.

  • Linha 54: Esta linha apresenta a Person $p como uma cadeia de caracteres. Para tal, é utilizado o método da classe Person denominado __toString.

5.5. A classe Person com verificações de validade no construtor (exemplo_18)

O construtor de uma classe é o local certo para verificar se os valores de inicialização do objeto estão corretos. No entanto, um objeto também pode ser inicializado através dos seus métodos set ou equivalentes. Para evitar a duplicação das mesmas verificações em dois locais diferentes, vamos colocá-las dentro dos métodos set. Se for detetado que o valor de inicialização de um objeto está incorreto, será lançada uma exceção. Aqui está um exemplo:


<?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;
?>

Resultados:

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

Comentários

  • linhas 23-30: inicialização do atributo first_name e verificação do valor de inicialização
  • linha 25: utilização de uma expressão regular. O nome próprio é uma sequência de um ou mais caracteres, possivelmente seguida ou precedida por espaços.
  • linha 26: se o apelido estiver vazio, é lançada uma exceção; caso contrário, o nome próprio é guardado (linha 28)
  • linha 66: utilização do construtor da classe Person
  • linha 68: utilização do método __toString da classe Person
  • Linhas 70–74: Tratamento de qualquer exceção lançada pelo construtor da classe Person.

5.6. Adicionar um método que atua como um segundo construtor (exemplo_19)

No PHP 5, não é possível ter múltiplos construtores com parâmetros diferentes que permitam que um objeto seja construído de várias maneiras. Podemos, portanto, utilizar métodos que atuam como construtores:


<?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;
?>

Resultados:

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

Comentários

  • linhas 26-29: O método initWithPerson permite atribuir os valores dos atributos de outro objeto Person ao objeto atual. Aqui, ele chama o construtor __construct, mas isso não é obrigatório.

5.7. Uma matriz de objetos Person (exemplo_20)

O exemplo seguinte mostra que é possível ter matrizes de objetos.


<?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;
?>

Resultados:

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

Comentários

  • linha 39: criação de uma matriz com 2 pessoas
  • linha 42: iteração pela matriz
  • linha 43: $group[$i] é um objeto do tipo Pessoa. O método __toString é utilizado para o exibir.

5.8. Criação de uma classe derivada da classe Pessoa (exemplo_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;
?>

Resultados:

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

Comentários

  • linhas 3-35: a classe Pessoa
  • linha 38: a classe Professor estende a classe Pessoa. A classe derivada Professor herda os atributos e métodos da sua classe pai.
  • linha 41: a classe Professor adiciona um novo atributo, disciplina, que é específico desta
  • linha 55: o construtor da classe Professor recebe 4 parâmetros
    • 3 para inicializar a sua classe pai (primeiro_nome, apelido, idade)
    • 1 para a sua própria inicialização (disciplina)
  • linha 57: a classe derivada tem acesso aos métodos e construtores da sua classe pai através da palavra-chave parent::. Aqui, passamos os parâmetros (first_name, last_name, age) para o construtor da classe pai.
  • linha 64: o método __toString da classe derivada utiliza o método __toString da classe pai.
  • linha 71: um array contendo um objeto Teacher e um objeto Person.
  • linha 74: percorremos os elementos da matriz
  • linha 75: será chamado o método __toString de cada elemento $group[$i]. A classe Person possui um método __toString. A classe Teacher possui dois: o da sua classe pai e o seu próprio. Poder-se-á perguntar qual deles será chamado. A execução mostra que foi o método da classe Teacher que foi chamado. É sempre assim: quando um método é chamado num objeto, ele é procurado na seguinte ordem: no próprio objeto, na sua classe pai, se tiver uma, depois na classe pai da classe pai, e assim por diante… A pesquisa pára assim que o método é encontrado.

5.9. Criar uma segunda classe derivada da classe Pessoa (exemplo_22)

O exemplo seguinte cria uma classe Student derivada da 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;
?>

Resultados:

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

5.10. Interfaces (exemplo_23)

Uma interface é uma estrutura que define protótipos de métodos. Uma classe que implementa uma interface define o código para todos os métodos da interface.


<?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);
?>

Resultados

17
21
127
201

Comentários

  • Linhas 4–8: A interface IExample define dois métodos: a função add (linha 5) e a função subtract (linha 7). A interface não define o código para estes métodos. As classes que implementam a interface farão isso.
  • Linha 11: A classe Class1 implementa a interface IExample. Por conseguinte, define o código para o método add (linha 13) e para o método subtract (linha 17).
  • Linhas 24–34: O mesmo se aplica à classe Class2.
  • Linha 37: O método *calculer recebe três parâmetros: dois inteiros, *$a* e $b*, e um objeto *$interface que implementa a interface *IExample. Poderíamos ter escrito function calculate($a, $b, $interface) sem especificar o tipo IExample do parâmetro *$interface*. Ao especificá-lo, permitimos que o interpretador PHP verifique se o parâmetro real é, de facto, um objeto que implementa a interface *IExample*.
  • linhas 38–39: utilização dos métodos add e subtract do objeto $interface. Como este implementa a interface IExample, sabemos que possui estes dois métodos.
  • Linhas 44–45: Criação de dois objetos de tipos diferentes, ambos implementando a interface IExample.
  • Linha 47: Passamos o objeto $c1 do tipo Class1, que implementa a interface IExample, para a função calculate.
  • Linha 48: O objeto $c2 do tipo Class2, que implementa a interface IExample, é passado para a função calculate.