Você está na página 1de 13

PHP e a programação orientada a objetos

A regra da programação é bem clara. Se um trecho de código se repete em, no mínimo, dois lugares,
transforme este trecho em uma função. O reaproveitamento de códigos deve estar sempre presente.

Outra forma que está sendo utilizada largamente em PHP, e que possibilita um salto
no reaproveitamento de códigos, é a Programação Orientada a Objetos (OOP). Contudo, OOP
em PHP é mais que reaproveitar códigos. É uma mudança radical na forma com que nossos códigos
são escritos.

Ao adotar a programação orientada a objetos, você começa a visualizar suas aplicações como um
conjunto de objetos do mundo real. Agora você terá objetos Cliente, Boleto, Fatura, Produto, etc. E
estes objetos possuirão métodos e características.

A grande vantagem da orientação a objetos é que a modularização de um sistema se torna mais


"controlável". Você pode ter alguém da equipe encarregada de escrever uma classe Boleto que
poderá ser usada para imprimir boletos da maioria dos bancos. A partir daí você nunca mais
precisará escrever códigos para impressão de boletos novamente. Basta criar uma instância da
classe, chamar um métodos e pronto! O boleto já será exibido e pronto para impressão.

Este grupo de anotações cobre a OOP no PHP 5. Esta versão suporta muitas das características da
OOP que não eram suportadas na versão 4. Assim, se estiver usando a versão 4 ou anteriores, faça a
atualização e vamos adiante.

Entendendo classes e objetos


Em PHP, uma classe é simplesmente um conjunto de instruções que executam uma determinada
tarefa. Uma classe típica contém tanto variáveis quanto funções, e serve como um modelo a partir
do qual uma instância específica desta classe será criada.

Esta instância específica da classe é chamada de objeto. Cada objeto tem certas características, ou
propriedades, e certas funções pré-definidas, ou métodos. Estas propriedades e métodos do objeto
correspondem diretamente às variáveis e métodos definidos na classe.

Após a definição da classe, a PHP permite-nos criar quantas instâncias desta classe quisermos. Cada
instância é um objeto completamente diferente, com suas próprias propriedades e métodos, e
portanto, pode ser manipulado independentemente de outros objetos. Isso se torna importante
quando precisamos de duas conexões simultâneas com uma base de dados ou dois carrinhos de
compras.

A forma mais comum de usar OOP em códigos PHP é definir as classes em arquivos separados e
incluir estes arquivos nas páginas onde objetos desta classe serão usados. Isso facilita a manutenção
do código das classes sem a necessidade de alterar páginas já disponibilizadas aos seus usuários.

Criando sua primeira classe em PHP


Agora que já temos uma idéia básica do funcionamento da orientação a objetos em PHP, chegou a
hora de escrevermos nossa primeira classe e ver uma instância desta classe, ou seja, um objeto, em
funcionamento.

Escreva o código PHP abaixo:


<?
// definição da classe Pessoa
class Pessoa{
public $nome;
public $idade;
public $sexo;

public function andar(){


echo "Executando o método andar()";
}
}
?>

A definição de uma classe PHP começa com a palavra class seguinda pelo nome da classe. No
corpo da definição inserimos as propriedades e métodos que esta classe terá. Em nosso exemplo, a
classe possui três propriedades e um método. Veja o uso da palavra-chave public para definir o
nível de visibilidade dos atributos e métodos da classe. Mais adiante você aprenderá mais sobre este
modificador e os demais.

Para criar uma instância desta classe você pode usar o seguinte código:

<?
// cria uma instância chamada $cliente
$cliente = new Pessoa();
?>

Pronto! A partir de agora a variável $cliente é um objeto da classe Pessoa e pode ter suas
propriedades alteradas independentemente de outras instâncias da mesma classe.

Veja, por exemplo, como alterar a propriedade $nome do objeto:

<?
// altera a propriedade nome do objeto
$cliente->nome = "Geraldo Gomes";
?>

Observe o uso do operador -> para acessar propriedades e métodos do objeto. Veja agora como
exibir esta alteração:

<?
// exibe o nome do cliente
echo $cliente->nome;
?>

Para finalizar, veja como chamar o método andar():

<?
// chama um método do objeto
$cliente->andar();
?>

Como exercício experimente colocar a definição da classe em um arquivo separado e incluí-la na


página de teste.
Controlando a visibilidade de propriedades e métodos de uma classe
O PHP 5 introduziu o conceito de visibilidade das propriedades e métodos de uma classe. Este é o
conceito do encapsulamento de dados, ou seja, você tem classes robustas e bem testadas que
fornecem acesso às suas funcionalidades somente através de alguns métodos públicos.

Imagine uma classe Impressora capaz de imprimir todos os tipos de documentos possíveis. É claro
que esta classe terá uma certa quantidade de propriedades e métodos. Porém, o usuário da classe
poderia ter acesso a apenas alguns métodos públicos, tais como imprimir(), definirTipo(), etc. As
propriedades e métodos que interessam somente ao funcionamento interno da classe podem ser
ocultos do mundo externo.

Veja a seguinte definição de classe:

class Pessoa{
public $nome;

public function andar(){


echo "Executando o método andar()";
}
}

Aqui tanto as propriedades e métodos são de acesso public e podem ser acessados e manipulados
por qualquer trecho de código que esteja usando um objeto da classe. Experimente agora usar o
modificador private. Este modificador marca um recurso para que este seja acessível somente à
classe a qual ele pertence. Veja:

// definição da classe Pessoa


class Pessoa{
private $nome;

public function andar(){


echo "Executando o método andar()";
}
}

Veja o que acontece quando tentamos executar o trecho de código abaixo:

// cria uma instância chamada $cliente


$cliente = new Pessoa();

// altera a propriedade nome do objeto


$cliente->nome = "Geraldo Gomes da Silva";

O resultado exibido pelo browser será:

Fatal error: Cannot access private property Pessoa::$nome in


c:\estudos\teste.php on line 10

Isso nos mostra que, de fato, recursos marcados como private são acessíveis somente à classe.
Desta forma, tais recursos podem ser acessados usando métodos public. Veja:

<?
// definição da classe Pessoa
class Pessoa{
private $nome;

public function getNome(){


return $this->nome;
}

public function setNome($nome){


$this->nome = $nome;
}
}

// cria uma instância chamada $cliente


$cliente = new Pessoa();

// altera a propriedade nome do objeto


$cliente->setNome("Geraldo Gomes da Silva");

// exibe o nome do cliente


echo $cliente->getNome();
?>

Veja que agora o nome do cliente é definido a partir do método public setNome:

public function setNome($nome){


$this->nome = $nome;
}

O identificador $this é usado para acessar recursos locais da classe. Os prefixos "set" e "get" são
muito usados para definir métodos que acessam ou alteram dados privados de uma classe. Veja o
método que obtém o nome:

public function getNome(){


return $this->nome;
}

Veja como usamos $this novamente para acessar a propriedade nome e devolvê-la na saída do
método.

O modificador protected é um pouco mais elaborado. Este modificador permite o acesso a


propriedades e métodos somente à classe a qual eles pertencem e a outras classes filhas desta
(através do recurso de herança). Adie o estudo deste modificador até o momento em que estiver
confiante em relação à herança.

Por padrão, ou seja, quando omitimos os modificadores, a visibilidade de propriedades


e métodos são public. No entanto, é necessário inserir a palavra-chave var antes
das propriedades da classe. Assim:

var $nome;
var $idade;

Para funções isso não é necessário.


Usando construtores e destrutores
O PHP nos permite executar códigos específicos quando objetos de nossas classes são
criados e destruídos. Para isso temos as funções __construct e __destruct. A função
__construct é chamada automaticamente quando um novo objeto da classe é construído. Veja um
exemplo:

<?
// definição da classe Pessoa
class Pessoa{
private $nome;

function __construct(){
echo "Novo objeto construído com sucesso!";
}
}

// cria uma instância chamada $cliente


$cliente = new Pessoa();
?>

Ao executar este código você terá o seguinte resultado:

Novo objeto construído com sucesso!

A função __destruct é chamada quando o objeto é destruído. Veja um exemplo:

<?
// definição da classe Pessoa
class Pessoa{
private $nome;

function __destruct(){
echo "O objeto foi destruído com sucesso!";
}
}

// cria uma instância chamada $cliente


$cliente = new Pessoa();
?>

Algo bem interessante acontece aqui. Execute o código e veja como o objeto é destruído
quando o código PHP no servidor termina sua execução. Se quiser destruir o objeto antes você pode
usar o seguinte código:

<?
// definição da classe Pessoa
class Pessoa{
private $nome;

function __destruct(){
echo "O objeto foi destruído com sucesso!";
}
}
// cria uma instância chamada $cliente
$cliente = new Pessoa();

// destrói o objeto $cliente


unset($cliente);

echo "<br>O objeto foi destruído antes da execução chegar aqui.";


?>

Fornecendo parâmetros de inicialização às suas classes

Vimos na lição anterior que o PHP nos fornece uma função que é executada no
momento em que um objeto de uma classe é construído. Podemos tirar proveito
desta funcionalidade e fornecer valores para algumas propriedades do nosso objeto.

Veja um exemplo em que fornecemos valores durante a construção de um objeto:

<?
// definição da classe Pessoa
class Pessoa{
public $nome;
public $idade;

function __construct($nome, $idade){


$this->nome = $nome;
$this->idade = $idade;
}
}

// cria uma instância chamada $cliente


$cliente = new Pessoa("Fábio Moraes", 34);

echo "O nome do cliente é: " . $cliente->nome . "<br>";


echo "A idade do cliente é: " . $cliente->idade;
?>

Experimente instanciar novos objetos fornecendo valores diferentes e veja o resultado.

Usando propriedades estáticas


Quando declaramos propriedades em uma classe, cada instância desta classe terá suas próprias
versões destas propriedades.

Existe, contudo, uma forma de fazer com que uma determinada propriedade pertença à classe e não
aos objetos instanciados a partir dela. Veja um exemplo curioso.

Suponha que você esteja desenvolvendo um jogo que contenha vários objetos da classe Marciano.
Ora, não seria interessante que cada objeto soubesse quantos colegas seus existem no momento?
Isso os faria mais ou menos corajosos.

A palavra-chave static é usada para marcar uma propriedade pertecendo à classe e não às suas
instâncias. Veja um exemplo:
<?
// definição da classe Pessoa
class Pessoa{
static $quant = 0;

function __construct(){
self::$quant++;
}

function __destruct(){
self::$quant--;
}
}

// cria quatro instâncias da classe


for($i = 0; $i < 4; $i++)
$cliente[$i] = new Pessoa();

// obtém o valor da propriedade $quant;


echo 'O valor de $quant é: ' . Pessoa::$quant;

// exclui um dos objetos


unset($cliente[0]);

// obtém o valor da propriedade $quant novamente;


echo '<br>O valor de $quant agora é: ' . Pessoa::$quant;
?>

Na linha:

static $quant = 0;

definimos uma variável estática chamada $quant e definimos seu valor como 0. Em seguida usamos
o construtor e destrutor da classe para incrementar ou decrementar o valor da variável. Veja que
temos que usar a palavra self acompanhada de :: para ter acesso a uma propriedade estática dentro
do corpo da classe:

self::$quant++;

Fora do corpo da classe nós usamos o nome da classe e :: como mostrado abaixo:

// obtém o valor da propriedade $quant;


echo 'O valor de $quant é: ' . Pessoa::$quant;

Usando métodos estáticos


Além de suportar propriedades estáticas, o PHP também suporta métodos estáticos, ou seja,
definidos com a palavra-chave static.

Métodos estáticos pertencem à classe e podem ser acessados sem a necessidade de se criar uma
instância da classe. Veja:
<?
// definição da classe Pessoa
class Pessoa{
static function avisar(){
echo "Sou um método estático";
}
}

// chama o método usando o nome da classe


Pessoa::avisar();
?>

Observe como chamamos o método sem criar uma instância da classe a qual ele pertence. Para isso
usamos o nome da classe e o operador :: seguido pelo nome do método.

Métodos estáticos são úteis quando você quer montar uma biblioteca de funções relacionadas. Um
exemplo seria uma classe Math com as funções matemáticas mais usadas em seus códigos.

É importante ter em mente que métodos estáticos não têm acesso a outros métodos ou propriedades
não estáticas da classe. Isso é fácil de entender. Como não existe uma instância da classe, estes
métodos e propriedades não existem. Veja o que acontece no código a seguir:

<?
// definição da classe Pessoa
class Pessoa{
public $nome;

static function avisar(){


$this->nome = "Alberto";
echo "Sou um método estático";
}
}

// chama o método usando o nome da classe


Pessoa::avisar();
?>

Ao executar este código teremos a seguinte mensagem de erro:

Fatal error: Using $this when not in object context in


c:\estudos\estudos.php on line 7

Uma saída seria usar self:

self::$nome = "Alberto";

Outra mensagem de erro:

Fatal error: Access to undeclared static property: Pessoa::$nome


in c:\estudos\estudos.php on line 7
Marque $nome como static e os erros desaparecerão:

public static $nome;

Como usar constantes como membros de classes


Constantes globais existem há muito tempo no PHP. Elas podem ser definidas com a função
define(). Veja:

<?
define("FATOR", "3.7");

// exibe o valor da constante


echo FATOR;
?>

Com o suporte mais avançado da programação orientada a objetos no PHP 5, constantes podem ser
definidas a nível de classes, ou seja, pertencentes à classe e não aos objetos instanciados a partir
dela. Em um primeiro momento, constantes definidas em uma classe se comportam exatamente
como propriedades estáticas e podem ser acessadas sem a necessidade de se criar uma instância da
classe.

A vantagem do uso de constantes em classes PHP é que podemos criar enumerações (tipos
enumerados). Um uso típico é quando temos valores númericos e gostaríamos de tratá-los por
apelidos em algumas partes do código. Veja um exemplo:

<?
// definição da classe Cores
class Cores{
const VERMELHO = "red";
const AZUL = "blue";
const PRETO = "black";
const AMARELO = "yellow";
}

// Exibe uma das cores da enumeração


echo "A cor selecionada foi: " . Cores::AZUL;
?>

Como o nome diz, constantes não podem ter seus valores alterados durante a execução do código.
Além disso, é prática comum usar constantes sempre em letras maiúsculas.

Atribuição de objetos de uma mesma classe


Uma das situações mais comuns é quando queremos atribuir um objeto de uma classe a um outro
objeto da mesma classe. Veja um exemplo:

<?
// definição da classe Pessoa
class Pessoa{
public $nome;
}

// Cria um objeto da classe Pessoa


$cliente = new Pessoa();
$cliente->nome = "Marcos de Souza";
echo $cliente->nome . "<br><br>";

// Cria um novo objeto da classe Pessoa


$cliente2 = new Pessoa();

// Atribui o primeiro objeto ao segundo


$cliente2 = $cliente;
echo $cliente2->nome . "<br><br>";

// Atribui o primeiro objeto a um terceiro


// sem usar a palavra-chave new
$cliente3 = $cliente;
echo $cliente3->nome;
?>

O importante a notar nestas atribuições é que todas elas acontecem por referência, ou
seja, qualquer alteração na propriedade de um dos três objetos afetará os demais. Veja:

$cliente3->nome = "Fernando Alves";


echo $cliente->nome . "<br><br>";
echo $cliente2->nome;

Para que isso não aconteça nós podemos clonar os objetos. Isso é demonstrado na
lição seguinte.

Aprenda a clonar objetos de uma mesma classe


Quando fazemos a atribuição de objetos de uma mesma classe, uma alteração em um dos objetos
afetará os demais. Para evitar isso podemos usar a palavra-chave clone para efetuar uma cópia
independente do objeto que queremos. Veja:

<?
// definição da classe Pessoa
class Pessoa{
public $nome;
}

// Cria um objeto da classe Pessoa


$cliente = new Pessoa();
$cliente->nome = "Marcos de Souza";

// Clona o primeiro objeto


$cliente2 = clone $cliente;

// Altera a propriedade do segundo objeto


$cliente2->nome = "Fernando Alves";

// As propriedades dos objetos continuam diferentes


echo $cliente->nome . "<br>";
echo $cliente2->nome;
?>
A execução deste código mostra que os objetos realmente são independentes agora. Existe, no
entando, uma situação em que a clonagem de objetos deve ser feita com muito cuidado. Se os
objetos possuirem referências a outros objetos, estas referências serão duplicadas, ou seja, os
objetos clonados continuarão atrelados de alguma forma.

Para resolver o problema, o PHP nos fornece o construtor de cópia. Veja como usá-lo no exemplo
anterior:

// definição da classe Pessoa


class Pessoa{
public $nome;

function __clone(){
echo "Acabei de ser clonado.";
}
}

Assim, se houver referências a outros objetos, o construtor de cópia é o lugar ideal para criar novas
instâncias das classes referenciadas. Veja um exemplo completo:

class MyFile{
function setFileName($file_name){
$this->file_name = $file_name;
}

function openFileForReading(){
$this->file_handle = fopen($this->file_name, "r");
}

function __clone(){
if($this->file_handle){
$this->file_handle = fopen($this->file_name, "r");
}
}

private $file_name;
private $file_handle = NULL;
}

Herança
Uma das facilidades de desenvolvimento trazidas pela programação orientada a objetos, é a
reutilização de códigos já desenvolvidos e testados. A herança nos possibilita derivar classes de
outras classes e adicionar novas propriedades e funções. Veja um exemplo:
<?
// definição da classe Pessoa
class Pessoa{
public $nome;
public $idade;
public $sexo;
}

// definicao da classe Cliente


class Cliente extends Pessoa{
public $codigo;
}

// Cria um objeto da classe Cliente


$cliente = new Cliente();
$cliente->nome = "Alberto Marques";
$cliente->codigo = 44664;

// Exibe os dados
echo $cliente->nome . "<br>";
echo $cliente->codigo;
?>

Veja que a classe Cliente herda todas as propriedades e métodos da classe Pessoa através da
palavra-chave extends. Agora a classe Cliente é chamada de sub-classe e a classe Pessoa é chamada
de superclasse ou classe base. Note que a classe Cliente possui inicialmente apenas uma
propriedade, mas, depois da herança, ela conterá quatro propriedades.

Em PHP uma classe pode herdar apenas de uma classe, ou seja, a herança múltipla não é permitida,
ainda que o uso de interfaces possibilite o mesmo efeito, como veremos mais adiante.

Herança, construtores e a palavra-chave parent


Quando estamos implementando herança em nossos códigos PHP, precisamos estar atentos à
questão dos construtores. Como sabemos, é possível fornecer parâmetros para a instância que
queremos criar através do método __construct da classe.

Imagine o cenário em que queremos passar parâmetros para o construtor de uma classe derivada.
Como acrescentamos mais propriedades à nova classe, é certo pensar que teremos que chamar
primeiro o construtor da super-classe, inicializar suas propriedades e só então chamar o construtor
da classe derivada, inicializando as propriedades adicionadas. Veja um exemplo:

<?
// definição da classe Pessoa
class Pessoa{
private $nome;
private $idade;

function __construct($nome, $idade){


$this->nome = $nome;
$this->idade = $idade;
}

public function getNome(){


return $this->nome;
}
}

// definicao da classe Cliente


class Cliente extends Pessoa{
private $codigo;

function __construct($nome, $idade, $codigo){


parent::__construct($nome, $idade);
$this->codigo = $codigo;
}
}

// Cria um objeto da classe Cliente


$cliente = new Cliente("Carlos Silva", 45, 5234);
echo $cliente->getNome();
?>

Veja que a classe pai possui as seguintes propriedades:

private $nome;
private $idade;

Como estas propriedades estão marcadas com o modificador private, elas não são
acessíveis a partir da classe derivada. A classe derivada, por sua vez, acrescenta a
propriedade:

private $codigo;

Veja o construtor da classe derivada:

function __construct($nome, $idade, $codigo){


parent::__construct($nome, $idade);
$this->codigo = $codigo;
}

Observe como usamos a palavra-chave parent para acessar o construtor da superclasse e instanciar
suas propriedades. Sem esta técnica, estas propriedades jamais poderiam ser acessadas e
modificadas a partir da classe derivada. Use-a para chamar qualquer método de uma classe pai.

Você também pode gostar