Quando a extensibilidade se torna vilã do paradigma O.O.

O título é bastante provocador, afinal, ao contrário do que ele sugere, o paradigma orientado a objetos propõe justamente oferecer alternativas mais elegantes para a extensão de uma classe.

Li o artigo intitulado Uniform Function Call Syntax (Bright, Walter) e foi uma interessante reflexão sobre as formas que utilizamos para estender as funcionalidades de uma classe já existente. As opções que tipicamente se apresentam:

1. Adicionar a nova funcionalidade diretamente na classe

Essa alternativa só é possível quando o código fonte da classe está disponível para nossa aplicação, o que nem sempre é o caso. Mesmo quando está acessível, nem sempre é conveniente fazê-lo: será que aquela funcionalidade justifica a sobrecarga que impomos à classe, e a provável violação do princípio da responsabilidade única?

2. Herança

Seria a maneira mais adequada, mas esbarra com uma limitação imposta por Java ou outras linguagens de herança simples: como combinar várias extensões? O exemplo do artigo é muito bom. Imagine a classe Integer do Java, e que eu quisesse adicionar a funcionalidade aoQuadrado numa subclasse de Integer. Outro colega necessita do método aoCubo e cria outra subclasse. Sem herança múltipla, como posso utilizar os dois métodos de maneira simples?

Além disso, nem sempre essa é uma opção: há classes que, justamente para evitar a confusão oriunda do descontrole sobre subclasses, colocam-as como ‘final’. Ou seja, estão seladas para herança.

3. Composição e Classe utilitária

As duas são maneiras mais elegantes, no meu ponto de vista, de adicionar a funcionalidade a uma classe existente. Digo isso do ponto de vista do encapsulamento. Sou capaz de adicionar a nova funcionalidade sem afetar a classe alvo. Mas não é chato ter que saber que existe uma classe IntegerUtil, ou, pior ainda, regredir do formato sintático tradicional que se aplica na orientação a objetos para o uso procedural? Não é muito melhor escrever objeto.metodo do que ClasseUtilitaria.fazAlgo(objeto) ?

Foi aí que esbarrei com essa nova modalidade de extensão: os métodos de extensão (Extension Method). Ele não difere do ponto de vista conceitual de uma classe utilitária. O diferencial dele é a forma de uso.

Não seria legal, ao invés de usar:

Integer resultado = IntegerUtil.aoQuadrado( meuInteger );

usar:

Integer resultado = meuInteger.aoQuadrado();

Pois é isso que os métodos de extensão habilitam. O código abaixo seria uma aproximação em C# da classe utilitária:

public static class IntegerUtil {
   public static Integer aoQuadrado(this Integer valor) {
      return valor * valor;
   }
}

O this, no código anterior, faz a mágica. Ainda não consegui relacionar o impacto desse novo recurso com as linguagens dinâmicas, como o Ruby. Alguma opinião?

Referências:

Bright, Walter. Uniform Function Call Syntax. Dr.Dobb’s. 2012.

Extension Method. Wikipedia. 12 October 2012.

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *


Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>