Header
We have launched our new Privacy Policy. You can read more about it here.
Advertisement

PHP Orientado a Objetos para Iniciantes

by

Portuguese (Português) translation by Erick Patrick (you can also view the original English article)

Para muitos programadores PHP, orientação a objetos é um conceito amedrontador, cheio de sintaxes complicadas e pontos de paradas. Com o mesmo detalhamento do meu livro, Pro PHP and jQuery, neste artigo você aprenderá os conceitos por trás da programação orientada a objetos (POO), um estilo de codificação onde ações relacionadas são agrupadas em classes para ajudar na criação de códigos mais compactos e efetivos.

Compreendendo a Programação Orientada a Objetos

Programação orientada a objetos é um estilo de programação que permite os desenvolvedores agruparem tarefas semelhantes em classes. Isso ajuda a mantermo-nos dentro do princípio "don't repeat yourself" (DRY) (em português, não se repita), além de faciltar a manutenção do código.

"Programação orientada a objetos é um estilo de programação que permite os desenvolvedores agruparem tarefas semelhantes em classes."

Um dos maiors benefícios da programação DRY é que, se alguma informação é alterada em seu programa, geralmente, só uma mudança é necessária para atualizar o código. Um dos maiores problemas para os desenvolvedores é ter de manter códigos onde os dados são declarados e redeclarados, acabando num jogo de pique esconde, em busca de funcionalidades e dados duplicados pelo código.

POO é intimidadora para uma grande quantidade de programadores porque ela introduz uma nova sintaxe e, a primeira vista, parece ser bem mais complexa que a simples programação procedural. Entretanto, se analisar bem, POO é bem direta e, fundamentalmente, uma abordagem mais simples para programação.

Compreendendo Objetos e Classes

Antes de lidar diretamente com as partes mais interessante da POO, um entendimento básico das diferenças entre objetos e classes é necessário. Essa seção falará sobre a base das classes, suas diferentes capacidades e alguns de seus usos.

Reconhecendo as Diferenças Entre Objetos e Classes

Fotos por Instant Jefferson e John Wardell

Quando programadores de longa data falam sobre objetos e classes, esses termos parecem permutáveis entre si. Porém, não é bem assim.

Logo de cara, há uma grande confusão na POO: quando programadores de longa data falam sobre objetos e classes, esses termos parecem permutáveis entre si. Porém, não é bem assim, mmesmo que a diferença entre eles seja um pouco complicada de perceber, no início.

Uma classe, por exemplo, é como uma planta baixa para uma casa. Ela define a forma da casa no papel, com as relações entre as diferentes partes da casa, claramente definidas e planejadas, mesmo a casa ainda não existindo.

Um objeto, por outro lado, seria a casa de verdade, construída de acordo com a planta baixa. Os dados guardados no objeto são como a madeira, fios e concreto que compoem a casa: sem a ordem criada pela planta baixa, são só um monte de materiais. Entretanto, quando tudo é colocado seguindo uma ordem, eles viram uma casa organizada de verdade e útil.

As classes servem de estrutura para os dados e ações, e usam essa informação para construir objetos. Mais de um objeto pode ser construido de uma mesma classe, ao mesmo tempo, cada um independente dos outros. Continuando a nossa analogia de classes e objetos em relação a construção, é parecida com a maneira que um condomínio de casas pode ser construído, usando a mesma planta baixa: 150 casas diferentes, todas bastante parecidas umas às outras, porém, contem
famílias e decorações diferentes por dentro.

Estruturando Classes

A sintaxe para criar uma classe é bem direta: declare-a usando a palavra chave class, seguida do nome da classe e um par de chaves ({}):

Após criar a classe, ela pode ser instanciada e guardada em alguma variável usando a palavra chave new:

Para vermos o conteúdo da classe, usamos var_dump():

Experimente isso, colocando todo o código anterior em um único arquivo php, chamado test.php na sua pasta local de testes:

Carregue a página no seu navegador, usando o endereço http://localhost/test.php (ou o endereço indicado pelo seu servidor local) e o resultado a seguir deve aparecer:

De uma forma bem simplória, você acabou de criar seu primeiro código em POO.

Definindo as Propriedades da Classe

Para adicionar dados à classe, usamos as propriedades, que são variáveis específicas à classe. Elas funcionam de forma parecida às variáveis normais, exceto que elas estão ligadas ao objeto e só podem ser acessadas usando o objeto.

Para adicionar uma propriedade a MyClass, adicione o seguinte trecho de código ao seu script:

A palavra chave public determina a visibilidade da propriedade, a qual você aprenderá mais sobre, nas próximas seções. Depois disso, a propriedade é nomeada usando os padrões básicos de nomeação de variáves, e, então, um valor é atribuído (embora propriedades de classe não necessitem de valores iniciais).

Para ver o valor da propriedade e mostrá-la no navegador, referencie o objeto o qual será feita a leitura, bem como a propriedade a ser lida, dessa forma:

Já que múltiplas instâncias de uma mesma classe podem existir, se um objeto em específico não for referenciado, o código não será capaz de determinar de qual objeto ler a propriedade. O uso da flecha (->) é um construto da POO no PHP que permite acessar as propriedades e métodos de um dado objeto.

Modifique o código do arquivo test.php para ler a propriedade ao invés de mostrar todo o conteúdo da classe, dessa forma:

Atualizando a página no seu navegador, você obtem isso, agora:

Definindo Métodos de Classe

Métodos são funções específicas das classes. Ações particulares que os objetos serão capazes de executar são definidas dentro das classes na forma de métodos.

Por exemplo, para criar métodos que atribuam e retornem o valor de uma propriedade de classe chamada $prop1, adicione o código a seguir:

Nota — POO permite que os objetos referenciem-se usando $this. Quando estiver dentro de um método, use $this da mesma forma que você usaria o nome do objeto fora da classe.

Para usar os métodos, execute-os da mesma forma que faria com funções normais, mas, antes, referencie o objeto ao qual eles pertencem. Para ler o valor da propriedade $prop1 da classe MyClass, depois altera-lo e, por fim, le-lo novamente, faça as seguintes alterações no código:

Atualize a página no seu navegador e você verá o resultado a seguir:

"O poder da POO mostra-se ao usar múltiplas instâncias da
mesma classe."

Quando atualizar a página do seu navegador, verá o resultado a seguir:

Como pode ver, POO mantém os objetos como entidades diferentes, o que torna fácil a separação de diferentes partes de código em pedaços pequenos e relacionados.

Métodos Mágicos em POO

Para facilitar o uso dos objetos, o PHP provê uma série de métodos mágicos, métodos especiais chamados quando certas ações comuns ocorrem com objetos. Isso permite executar várias tarefas úteis com certa facilidade.

Usando Construtores e Destruidores

Quando um ojeto é instanciado, é desejável que algumas coisas ocorram de cara. Para lidar com isso, o PHP provê o método __construct(), que é chamado automaticamente quando um novo objeto é
criado.

Para ilustrar os conceitos dos construtores, adicione um construtor à classe MyClass que mostre uma mensagem todoa vez que uma nova instância for criada:

Nota__CLASS__ retorna o nome da classe na qual foi usado; isso é o que chamaos de constante mágica. Há inúmeras constantes mágicas disponíveis e você pode ler mais sobre elas no manual do PHP.

Atualize a página no seu navegador e terá os resultados a seguir:

Para chamar uma função quando um objeto for destruído, o método mágico __destruct() está disponível. Ele é útil para finalizar as tarefas da classe (encerrar uma conexão com a base de dados, por exemplo).

Mostre uma mensagem quando um objeto for destruído usando o método mágico
__destruct() na class MyClass:

Com um método destruidor definido, atualize a página no seu navegador e verá o resultado a seguir:

"Quando o fim do arquivo é alcançado, o PHP libera, automaticamente, todos os recursos."

Para executar, explicitamente, o método destruidor, você pode destruir o objeto usando a função
unset():

Os resultados das mudanças aparecerão assim que você atualizar a página no seu navegador:

Convertendo Em Uma String

Para evitar que aconteça um erro quando – e se – algum script tentar mostrar a classe MyClass como uma string, existe outro método mágico, chamado __toString().

Sem o método __toString(), tentar mostrar um objeto como uma string resulta em um erro fatal. Tente mostrar um objeto, usando echo, sem o método mágico:

O resultado é esse:

Para evitar esse erro, adicione o método __toString() method:

Nesse caso, tentar converter o objeto em string resulta numa chamada ao método getProperty(). Execute o código, recarregando a página no seu navegador, e veja o resultado:

Dica — Além dos métodos mágicos discutidos nessa seção, inúmeros outros estão disponíveis. Para uma lista completa, com todos os métodos mágicos, veja a respectiva página do manual do PHP.

Usando Herança de Classe

Classes podem herdar métodos e propriedades de outra classe usando a palavra chave extends. Por exemplo, para criar uma segunda classe que estenda MyClass e adicione um outro método, você faria dessa forma:

Após atualizar a página no seu navegador, você terá o seguinte resultado:

Sobrescrevendo Métodos e Propriedades Herdadas

Para alterar uma propriedade ou o comportamento de um método existente na nova classe, você pode, simplesmente, sobrescreve-los, bastando redeclará-los na nova classe:

As mudanças no resultado serão:

Preservando Funcionalidades Originais de um Método Enquanto Sobrescreve o Mesmo

Para adicionar uma nova funcionalidade a um método e, ao mesmo tempo, manter a funcionalidade do método original intacta, use a palavra chave parent juntamente ao operador de resolução de escopo (::):

Dessa forma, será retornado tanto o que foi codificado no construtor pai quando o do construtor da nova classe:

Atribuindo Visbilidade a Propriedades e Métodos

Para controle adicional sobre objetos, métodos e propriedades, atribuímos visibilidades a eles. Essa visibilidade controla como e de onde as propriedades podem ser acessadas. Há três palavras chaves para visibilidade: public, protected, e private. Em adição à sua visibilidade, um método ou propriedade pode ser declarado como static, o que permite que sejam acessados sem uma instanciação da classe.

"Para controle adicional sobre objetos, métodos e propriedades, atribuímos visibilidades a eles."

Nota — Visibilidade é um novo recurso presente a partir do PHP 5. Para maiores informações sobre a compatibilidade da POO com o PHP 4, veja a respectiva página do manual do PHP.

Métodos e Propriedades Públicas

Todos os métodos e propriedades que usamos, até agora, eram públicos. Isso significa que eles podem ser acessados de qualquer lugar, tanto dentro quanto fora da classe.

Métodos e Propriedades Protegidas

Quando uma propriedades ou método é declarada com protected, ela só pode ser acessada dentro dela própria ou por uma classe descendente (classes que estendem a classe que contem o método protegido).

Declare o método getProperty() como protegido, na classe MyClass, e tente acessá-lo diretamente fora da classe:

Quando tentar executar esse código, o erro a seguir aparece:

Agora, crie um método em MyOtherClass que invoque o método getProperty():

E, assim, temos o resultado desejado:

Métodos e Propriedades Privadas

Uma propriedade ou método declarado com private é acessível somente dentro da classe que os define. Isso significa que mesmo se uma classe estender a classe que define uma propriedade privada, aquela propriedade (ou método) não será acessível na classe filha.

Para demonstrar isso, declare getProperty() como privada dentro da classe MyClass, e tente invocar callProtected() da classe
MyOtherClass:

Atualize a página no seu navegador e verá o erro a seguir aparecer:

Métodos e Propriedades Estáticas

Um método ou propriedade declarada com static podem ser acessados sem, primeiro, instanciar a classe; você pode, simplesmente, usar o nome da classe, o operador de resolução de escopo e o nome da propriedade ou do método.

"Um dos maiores benefícios de se usar propriedades estáticas é que elas são capazes de manter os valores guardados dentro dela enquanto o arquivo for executado."

Para demonstrar isso, adicione uma propriedade estática chamada $count e um método estático chamado plusOne() à classe MyClass. Depois, prepare um laço de repetição do...whilepara mostrar o valor incrementado da proprieade $count enquanto o valor dela for menor que 10:

Nota — Quando acessar propriedades estáticas, o símbolo de dólar
($) vem depois do operador de resolução de escopo.

Quando atualizar a página do seu navegador, o resultado será:

Comentários com DocBlocks

"O estilo de comentários DocBlock é um
meio bem aceito para documentar classes."

Embora não seja uma parte oficial da POO, os comentários DocBlock são um meio bem aceito para documentar classes. Além de prover um padrão para os
desenvolvedores ao escreverem seus códigos, ele também foi adotado pela maioria dos kits de desenvolvimento de software (do inglês, software development kits - SDKs) populares, como o Eclipse e NetBeans, e serão usados para gerar dicas/indicações de códigos.

Um DocBlock é definido como um bloco de comentário que começa com um asterisco adicional:

O verdadeiro poder do DocBlocks vem com a possibilidade de usarmos as tags, que começam com o símbolo de localização (@) e são, imediatamente, seguidos dos nome e valor da tag. As tags do DocBlock permitem aos desenvolvedores definirem os autores de um arquivo, a licença que a classe usa, informações das propriedades e métodos e outras informações úteis.

As tags mais usadas são:

  • @author: Os autores do elemento atual (o qual pode ser uma classe, arquivo, método ou qualquer trecho de código) são listados usando essa tag. Múltiplas tags para autores podem ser usadas no mesmo DocBlock se precisar creditar mais de um autor. O formato para o nome do autor é Erick Patrick <erick.patrick@email.com>.
  • @copyright: Isso indica o ano e o nome de quem tem os direitos sobre o elemento atual. O formato é 2010 Nome da pessoa.
  • @license: Indicamos a licença usada no elemento atual. O formato para a informação da licença é
    http://www.example.com/path/to/license.txt Nome da licença.
  • @var: Isso indica o tipo e a descrição de uma variável ou de uma propriedade de classse. O formato é tipo do elemento descrição.
  • @param: Essa tag mostra o tipo e descrição de um parâmetro de uma função ou método. O formato é tipo $nome_do_elemento descrição do elemento.
  • @return: O tipo e descrição do valor retornado por uma função ou método. O formato é tipo descrição do valor retornado.

Uma classe exemplo, comentada com DocBlocks, parece-se com isso:

Uma vez que você dá uma rápida olha na classe acima, os benefícios do DocBlock tornam-se visíveis: tudo está claramente definido, de forma que o próximo desenvolvedor possa pegar esse código e nunca precisar imagina o que uma certa parte de código faz ou deveria receber.

Comparando Código Orientado a Objetos e Código Procedural

Não há maneira certo ou errada de programar. Isso dito, essa seção mostrar bons argumentos para adotar a abordagem orientada a objetos no desenvolvimento de software, especialmente em aplicações de grande porte.

Razão 1: Facilidade de Implementação

"Embora, inicialmente, pareça complicada, POO provê uma abordagem mais fácil para lidar com dados."

Embora, inicialmente, pareça complicada, POO provê uma abordagem mais fácil para lidar com dados. Uma vez que objetos podem guardar dados internamente, variáveis não precisam ser passadas para funções para que elas funcionem corretamente.

E como várias instâncias de uma mesma classe podem existir simultanemanete, lidar com conjuntos de dados grandes se torna infinitamente mais fácil. Por exemplo, imagine que há informações de duas pessoas sendo processadas ao mesmo tempo em um arquivo. Elas precisam de nomes, ocupações e idades.

A Abordagem Procedural

Eis a abordagem procedural para nosso exemplo:

Quando executado, o código mostrará o seguinte:

Apesar disso não estar tão ruim, tem muita coisa a ser lembrada de uma só vez. O conjunto de atributos da pessoa que foi afetado tem de ser passado e retornado de cada invocação de função, e isso possibilita o aparecimento de erros.

Para melhorar esse exemplo, seria desejável deixar o mínimo para o programador quanto possível. Só a informação extremamente essencial para a operação atual é necessária ser passada para as funções.

É aqui que a POO entra e ajuda você a ajustar as coisas.

A Abordagem POO

Eis a abordagem POO para nosso exemplo:

O seguinte seria mostrado no navegador:

É necessário um pouco mais de preparação na abordagem orientada a objetos, mas, uma vez definida a classe, criar e modificar pessoas é fácil; a informação de uma pessoa não precisa ser passada ou retornada para os métodos e só a informação essencial é passada para cada método.

"POO reduzirá significantemente a carga de trabalho se implementada corretamente."

A primeira vista, a diferença pode não parecer tanta, mas, de acordo com que sua aplicação cresce, POO reduzirá significanetemente a carga de trabalho se implementada corretamente.

DicaNem tudo precisa ser implementado em orientação a objetos. Uma função rápida, que lida com algo pequeno em um único lugar dentro da aplicação, não precisa, necessariamente, estar envolta em uma classe. Use seu melhor julgamento quando precisar decidir entre as abordagens orientada a objetos ou procedural.

Razão 2: Melhor Organização

Outro benefício da POO é a facilidade de empacotamento e catalogação. Cada classe, geralmente, é mantida sozinha em seu próprio arquivo e, se uma convenção de nomenclatura for usada, acessar as classes será extremamente fácil.

Assuma que você tem uma aplicação com 150 classes que são invocadas dinamicamente através de um arquivo controlador na pasta raiz da sua aplicação. Todas as 150 classes foram nomeadas como class._nome_da_classe_.inc.php e ficar dentro de um diretório chamado inc da sua aplicação.

O controlador implementa a função __autoload() do PHP para carregar dinamicamente as classes que ele precisa executar, ao invés de incluir todas as 150 classes dentro do controlador ou, até mesmo, usar uma maneira "mais esperta" de incluir esses arquivos no seu código:

Ao termos cada classe separada em seu próprio arquivo, tornamo-as mais portáteis e fáceis de reusar em novas aplicações, sem precisar copiar e colar para todos os lados.

Razão 3: Manutenção Mais Fácil

Devido a natureza compacta do PHP quando programado corretamente, mudanças no código, geralmente, são mais fáceis de perceber e alterar que em uma implementação procedural gigantesca e spaghetti.

Se um conjunto particular de informação ganha um novo atributo, códigos procedurais podem requerer (no pior dos casos) que o novo atributo seja adicionado a cada funcção que usa tal conjunto.

Uma aplicação POO poderia, potencialmente, ser atualizada, bastando adicionar uma nova propriedade e os métodos relacionados que lidam com tal propriedade a uma classe.

Vários benefícios cobertos nessa seção são produto da combinação de POO com práticas de programação DRY. Claro, é possível criar código procedural que seja fácil de manter e que não cause dores-de-cabeça, porém, é igualmente fácil criar código horroroso usando orientação a objetos. [Pro PHP and jQuery] tentará mostrar a combinação de boas práticas de programação com POO para gerar códigos claros e fáceis de ler e manter.

Resumo

A essa altura, espero que você se sinta confortável com o estilo de programação orientado a objetos. Aprender POO é uma ótima maneira de elevar o seu nível de programação. Quando implementada corretamente, POO gera código fácil de ler, manter e portátil, que salvará você (e os desenvolvedores que trabalham com você) horas de trabalho extra. Você está encucado com algo que não foi apresentado nesse artigo? Você já usa POO e tem algumas dicas para os iniciantes? Compartilhe nos comentários!

Nota do Autor — Esse tutorial é um extrato do livro Pro PHP and jQuery (Apress, 2010).

Seja o primeiro a saber sobre novas traduções–siga @tutsplus_pt no Twitter!

Advertisement