Resumo: Este artigo discutirá o conceito de polimorfismo e sua aplicação no design orientado a objetos. Também analisará como usar o polimorfismo no PHP 5 e suas vantagens e desvantagens.
O suporte para vinculação tardia foi implementado em versões recentes do PHP. Claro, ainda existem muitos problemas ao usar sua função de ligação tardia. Se você estiver usando uma versão mais antiga do PHP (meu servidor está executando o PHP 5.0.1), poderá descobrir que falta suporte para ligação tardia. Portanto, observe que o código neste artigo pode não funcionar na sua versão específica do PHP 5.
1. PHP 5 e Polimorfismo
Este artigo gostaria de discutir uma das partes mais importantes da programação orientada a objetos – o projeto do polimorfismo. Para ilustrar o problema, estou usando o PHP 5. Antes de continuar lendo, deixe claro que este artigo não é inteiramente sobre PHP. Embora a linguagem tenha feito grandes avanços em rápido desenvolvimento nas duas últimas versões principais, seu suporte a objetos ainda tem algum tempo pela frente antes que possa rivalizar com linguagens mais maduras, como C++ ou Java.
Se você é iniciante em programação orientada a objetos, este artigo pode não ser adequado para você, pois essa parte do polimorfismo é especial: depois de entendê-la, você nunca mais a esquecerá. Se você deseja aprender um pouco sobre programação e design de objetos e não sabe bem o que significa quando alguém diz “um objeto é polimórfico”, então este artigo é para você.
Ao final deste artigo, você deverá saber o que é polimorfismo e como aplicá-lo ao design orientado a objetos, e compreenderá as vantagens e desvantagens da programação de objetos no PHP 5.
2. O que é polimorfismo?
A definição de polimorfismo do dicionário.com é “ocorrendo em diferentes formas, estágios ou tipos em organizações independentes ou na mesma organização sem diferença fundamental”. A partir desta definição, podemos pensar que o polimorfismo Sexualidade é uma forma de programação de descrever o mesmo. objeto através de vários estados ou fases. Na verdade, seu verdadeiro significado é que, no desenvolvimento real, precisamos apenas nos concentrar na programação de uma interface ou classe base e não precisamos nos preocupar com a classe (classe) específica à qual um objeto pertence.
Se você estiver familiarizado com padrões de projeto, mesmo que tenha apenas um conhecimento preliminar, entenderá esse conceito. Na verdade, o polimorfismo pode ser a melhor ferramenta na programação de design baseada em padrões. Permite-nos organizar objetos semelhantes de forma lógica para que não tenhamos que nos preocupar com o tipo específico do objeto durante a codificação, além disso, precisamos apenas programar uma interface ou classe base desejada; Quanto mais abstrata for uma aplicação, mais flexível ela se tornará – e o polimorfismo é uma das melhores maneiras de abstrair o comportamento.
Por exemplo, vamos considerar uma classe chamada Pessoa. Podemos subclassificar Person com classes chamadas David, Charles e Alejandro. Person possui um método abstrato AcceptFeedback() e todas as subclasses devem implementar este método. Isso significa que qualquer código que use uma subclasse da classe base Person pode chamar o método AcceptFeedback(). Você não precisa verificar se o objeto é um David ou um Alejandro, basta saber que é uma Pessoa. Como resultado, seu código só precisa se concentrar no "menor denominador comum" - a classe Person.
A classe Person neste exemplo também poderia ser criada como uma interface. Claro, existem algumas diferenças em relação ao anterior, principalmente: uma interface não fornece nenhum comportamento, mas apenas determina um conjunto de regras. Uma interface Person requer "Você deve oferecer suporte ao método AddFeedback()", enquanto uma classe Person pode fornecer algum código padrão para o método AddFeedback() - sua compreensão disso pode ser "Se você não optar por oferecer suporte a AddFeedback(), então Você deve fornecer uma implementação padrão. "Como escolher uma interface ou uma classe base está além do tópico deste artigo; no entanto, em geral, você precisa implementar um método padrão por meio da classe base. Você também pode usar uma interface se puder simplesmente delinear um conjunto desejado de funcionalidades que sua classe implementa.
3. Aplicando design polimórfico
Continuaremos usando o exemplo da classe base Person e agora analisaremos uma implementação não polimórfica. Os exemplos a seguir usam diferentes tipos de objetos Person – uma forma de programação muito insatisfatória. Observe que a classe Person real é omitida. Até agora, nos preocupamos apenas com a questão das chamadas de código.
<?php
$nome = $_SESSION['nome'];
$minhaPessoa = Pessoa::GetPerson($nome);
switch (get_class($minhaPerson)){
caso 'David':
$myPerson->AddFeedback('Ótimo artigo!', 'Algum leitor', date('Ym-d'));
quebrar;
caso 'Carlos':
$myPerson->feedback[] = array('Algum leitor', 'Ótima edição!');
quebrar;
caso 'Alejandro':
$myPerson->Feedback->Append('Javascript incrível!');
quebrar;
padrão :
$myPerson->AddFeedback('Oba!');
}
?>
Este exemplo mostra objetos com comportamentos diferentes, e uma instrução switch é usada para distinguir diferentes objetos da classe Person, de modo a executar suas respectivas operações corretas. Observe que os comentários aqui são diferentes para diferentes condições. Este pode não ser o caso no desenvolvimento de aplicações reais. Simplesmente ilustro as diferenças que existem nas implementações de classes.
Um exemplo abaixo usa polimorfismo.
<?php
$nome = $_SESSION['nome'];
$minhaPessoa = Pessoa::GetPerson($nome);
$myPerson->AddFeedback('Ótimo artigo!', 'SomeReader', date('Ym-d'));
?>
Observe que não há nenhuma instrução switch aqui e, o mais importante, há uma falta de informações sobre que tipo de objeto Person::GetPerson() retornará. E o outro Person::AddFeedback() é um método polimórfico. O comportamento é completamente encapsulado por classes concretas. Lembre-se, quer estejamos usando David, Charles ou Alejandro aqui, o código de chamada nunca precisa saber o que a classe concreta faz, apenas a classe base.
Embora meu exemplo não seja perfeito, ele demonstra o uso básico do polimorfismo da perspectiva do código de chamada. Agora precisamos analisar a implementação interna dessas classes. Uma das grandes vantagens de derivar de uma classe base é que a classe derivada pode acessar o comportamento da classe pai. Essa geralmente é a implementação padrão, mas também pode ocorrer em cadeias de herança de classe para criar um comportamento mais complexo. Abaixo está uma demonstração simples desta situação.
<?php
classe Pessoa{
function AddFeedback($comentário, $remetente, $data){
//Adicionar feedback ao banco de dados}
}
classe David estende Pessoa{
function AdicionarFeedback($comentário, $remetente){
pai::AddFeedback($comment, $sender,
data('Ym-d'));
}
}
?>
Aqui, o método Person::AddFeedback é chamado pela primeira vez na implementação do método AddFeedback na classe David. Você pode notar que ele imita a sobrecarga de métodos em C++, Java ou C#. Tenha em mente que este é apenas um exemplo simplificado e o código real que você escreve depende completamente do seu projeto real.
4. Ligação tardia em PHP 5
Na minha opinião, ligação tardia é uma razão importante pela qual Java e C# são tão atraentes. Eles permitem que métodos da classe base chamem métodos usando "this" ou $this (mesmo que eles não existam na classe base ou a chamada de um método na classe base possa ser substituída por outra versão na classe herdada). Você pode considerar as seguintes implementações permitidas em PHP:
<?php
classe Pessoa{
function AddFeedback($messageArray) {
$this->ParseFeedback($messageArray);
//Escreve no banco de dados}
}
classe David estende Pessoa{
function ParseFeedback($messageArray){
// Faça algumas análises}
}
?>
Lembre-se, não há ParseFeedback na classe Person. Agora, supondo que você tenha esta parte do código de implementação (para este exemplo), isso fará com que $myPerson seja um objeto David:
<?php
$minhaPessoa = Pessoa::GetPerson($nome);
$myPerson->AddFeedback($messageArray);
?>
Ocorreu um erro de análise! A mensagem de erro geral é que o método ParseFeedback não existe ou alguma informação semelhante. Vamos falar sobre vinculação tardia no PHP 5! A seguir, vamos resumir o conceito de vinculação tardia.
Ligação tardia significa que a chamada do método não está vinculada ao objeto de destino até o último momento. Isso significa que quando o método é chamado em tempo de execução, esses objetos já possuem um tipo concreto. Em nosso exemplo acima, você chamou David::AddFeedback(), e como $this em David::AddFeedback() se refere a um objeto David, você pode assumir logicamente que o método ParseFeedback() existe - mas na verdade ele não existe existe porque AddFeedback() é definido em Person e ParseFeedback() é chamado a partir da classe Person.
Infelizmente, não existe uma maneira fácil de eliminar esse comportamento no PHP 5. Isso significa que você pode ficar um pouco impotente quando quiser criar uma hierarquia de classes polimórfica flexível.
Devo salientar que escolhi o PHP 5 como linguagem de expressão para este artigo simplesmente porque: esta linguagem não realiza a abstração perfeita do conceito de objeto! Isso é compreensível já que o PHP 5 ainda está em sua versão beta. Além disso, agora que classes e interfaces abstratas foram adicionadas à linguagem, a ligação tardia também deve ser implementada.
5. Resumo
Neste ponto, você deve ter um entendimento básico do que é polimorfismo e por que o PHP 5 não é perfeito para alcançar polimorfismo. Em geral, você deve saber como usar um modelo de objeto polimórfico para encapsular o comportamento condicional. Claro, isso aumenta a flexibilidade dos seus objetos e significa menos código para implementar. Além disso, você aumenta a clareza do seu código encapsulando o comportamento que satisfaz determinadas condições (dependendo do estado do objeto).