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:

PHP oop

Embed Size (px)

Citation preview

Page 1: PHP oop

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 saltono reaproveitamento de códigos, é a Programação Orientada a Objetos (OOP). Contudo, OOPem PHP é mais que reaproveitar códigos. É uma mudança radical na forma com que nossos códigossão escritos.

Ao adotar a programação orientada a objetos, você começa a visualizar suas aplicações como umconjunto de objetos do mundo real. Agora você terá objetos Cliente, Boleto, Fatura, Produto, etc. Eestes 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 quepoderá ser usada para imprimir boletos da maioria dos bancos. A partir daí você nunca maisprecisará escrever códigos para impressão de boletos novamente. Basta criar uma instância daclasse, 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 daOOP que não eram suportadas na versão 4. Assim, se estiver usando a versão 4 ou anteriores, faça aatualização e vamos adiante.

Entendendo classes e objetos Em PHP, uma classe é simplesmente um conjunto de instruções que executam uma determinadatarefa. Uma classe típica contém tanto variáveis quanto funções, e serve como um modelo a partirdo 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, oupropriedades, e certas funções pré-definidas, ou métodos. Estas propriedades e métodos do objetocorrespondem 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. Cadainstância é um objeto completamente diferente, com suas próprias propriedades e métodos, eportanto, pode ser manipulado independentemente de outros objetos. Isso se torna importantequando precisamos de duas conexões simultâneas com uma base de dados ou dois carrinhos decompras.

A forma mais comum de usar OOP em códigos PHP é definir as classes em arquivos separados eincluir estes arquivos nas páginas onde objetos desta classe serão usados. Isso facilita a manutençãodo 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 ahora de escrevermos nossa primeira classe e ver uma instância desta classe, ou seja, um objeto, emfuncionamento.

Escreva o código PHP abaixo:

Page 2: PHP oop

<? // 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. Nocorpo da definição inserimos as propriedades e métodos que esta classe terá. Em nosso exemplo, aclasse possui três propriedades e um método. Veja o uso da palavra-chave public para definir onível de visibilidade dos atributos e métodos da classe. Mais adiante você aprenderá mais sobre estemodificador 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 suaspropriedades 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 comoexibir 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 napágina de teste.

Page 3: PHP oop

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 é oconceito do encapsulamento de dados, ou seja, você tem classes robustas e bem testadas quefornecem 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. É claroque esta classe terá uma certa quantidade de propriedades e métodos. Porém, o usuário da classepoderia ter acesso a apenas alguns métodos públicos, tais como imprimir(), definirTipo(), etc. Aspropriedades e métodos que interessam somente ao funcionamento interno da classe podem serocultos 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 manipuladospor qualquer trecho de código que esteja usando um objeto da classe. Experimente agora usar omodificador private. Este modificador marca um recurso para que este seja acessível somente àclasse a qual ele pertence. Veja:

// definição da classe Pessoaclass 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 inc:\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

Page 4: PHP oop

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 clienteecho $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ãomuito usados para definir métodos que acessam ou alteram dados privados de uma classe. Veja omé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 dométodo.

O modificador protected é um pouco mais elaborado. Este modificador permite o acesso apropriedades 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 estiverconfiante em relação à herança.

Por padrão, ou seja, quando omitimos os modificadores, a visibilidade de propriedadese métodos são public. No entanto, é necessário inserir a palavra-chave var antesdas propriedades da classe. Assim:

var $nome;var $idade;

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

Page 5: PHP oop

Usando construtores e destrutores O PHP nos permite executar códigos específicos quando objetos de nossas classes sãocriados 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 umexemplo:

<?// definição da classe Pessoaclass 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 Pessoaclass 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ídoquando o código PHP no servidor termina sua execução. Se quiser destruir o objeto antes você podeusar o seguinte código:

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

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

Page 6: PHP oop

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

// destrói o objeto $clienteunset($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 nomomento em que um objeto de uma classe é construído. Podemos tirar proveitodesta 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 Pessoaclass 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 . "<b r>";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ópriasversões destas propriedades.

Existe, contudo, uma forma de fazer com que uma determinada propriedade pertença à classe e nãoaos 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 suasinstâncias. Veja um exemplo:

Page 7: PHP oop

<?// definição da classe Pessoaclass Pessoa{ static $quant = 0;

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

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

// cria quatro instâncias da classefor($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 objetosunset($cliente[0]);

// obtém o valor da propriedade $quant novamente;echo '<br>O valor de $quant agora é: ' . Pessoa::$q uant; ?>

Na linha:

static $quant = 0;

definimos uma variável estática chamada $quant e definimos seu valor como 0. Em seguida usamoso construtor e destrutor da classe para incrementar ou decrementar o valor da variável. Veja quetemos que usar a palavra self acompanhada de :: para ter acesso a uma propriedade estática dentrodo 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 umainstância da classe. Veja:

Page 8: PHP oop

<?// definição da classe Pessoaclass Pessoa{ static function avisar(){ echo "Sou um método estático"; } }

// chama o método usando o nome da classePessoa::avisar(); ?>

Observe como chamamos o método sem criar uma instância da classe a qual ele pertence. Para issousamos 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. Umexemplo 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 propriedadesnão estáticas da classe. Isso é fácil de entender. Como não existe uma instância da classe, estesmétodos e propriedades não existem. Veja o que acontece no código a seguir:

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

static function avisar(){ $this->nome = "Alberto"; echo "Sou um método estático"; } }

// chama o método usando o nome da classePessoa::avisar(); ?>

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

Fatal error: Using $this when not in object context inc:\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::$nomein c:\estudos\estudos.php on line 7

Page 9: PHP oop

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çãodefine(). Veja:

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

// exibe o valor da constanteecho FATOR; ?>

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

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

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

// Exibe uma das cores da enumeraçãoecho "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 outroobjeto da mesma classe. Veja um exemplo:

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

// Cria um objeto da classe Pessoa$cliente = new Pessoa();

Page 10: PHP oop

$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, ouseja, 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 naliçã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 objetosafetará os demais. Para evitar isso podemos usar a palavra-chave clone para efetuar uma cópiaindependente do objeto que queremos. Veja:

<?// definição da classe Pessoaclass 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 diferentesecho $cliente->nome . "<br>";echo $cliente2->nome;?>

Page 11: PHP oop

A execução deste código mostra que os objetos realmente são independentes agora. Existe, noentando, uma situação em que a clonagem de objetos deve ser feita com muito cuidado. Se osobjetos possuirem referências a outros objetos, estas referências serão duplicadas, ou seja, osobjetos 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 exemploanterior:

// definição da classe Pessoaclass 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 novasinstâ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, é areutilização de códigos já desenvolvidos e testados. A herança nos possibilita derivar classes deoutras classes e adicionar novas propriedades e funções. Veja um exemplo:

Page 12: PHP oop

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

// definicao da classe Clienteclass Cliente extends Pessoa{ public $codigo;}

// Cria um objeto da classe Cliente$cliente = new Cliente();$cliente->nome = "Alberto Marques";$cliente->codigo = 44664;

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

Veja que a classe Cliente herda todas as propriedades e métodos da classe Pessoa através dapalavra-chave extends. Agora a classe Cliente é chamada de sub-classe e a classe Pessoa é chamadade superclasse ou classe base. Note que a classe Cliente possui inicialmente apenas umapropriedade, 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 quequeremos 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 chamarprimeiro o construtor da super-classe, inicializar suas propriedades e só então chamar o construtorda classe derivada, inicializando as propriedades adicionadas. Veja um exemplo:

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

function __construct($nome, $idade){ $this->nome = $nome; $this->idade = $idade; }

public function getNome(){

Page 13: PHP oop

return $this->nome; } }

// definicao da classe Clienteclass 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ãoacessíveis a partir da classe derivada. A classe derivada, por sua vez, acrescenta apropriedade:

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 instanciarsuas propriedades. Sem esta técnica, estas propriedades jamais poderiam ser acessadas emodificadas a partir da classe derivada. Use-a para chamar qualquer método de uma classe pai.