Construtores Virtuais


A linguagem Object Pascal possui uma feature que não existe em nenhuma outra linguagem mainstream do mercado.

Unsplash image Photo by Eddie Kopp on Unsplash

Introdução

Construtores Virtuais permitem a criação customizada de novas instâncias sem a necessidade do uso de classes de fábricas.

É possível que desenvolvedores Object Pascal ao redor do mundo utilizem essa feature diariamente mesmo sem saber que só é possível utilizá-la na linguagem Object Pascal.

Toda classe possui um ou mais construtores no qual são responsáveis por instanciar um novo objeto.

Entretanto, ter um construtor virtual não é comum em outras linguagens.

Diferentemente das demais linguagens, os construtores na linguagem Object Pascal são como métodos “marcados” para serem construtores. Um fato sobre isso é que, em Object Pascal, podemos dar o nome que quisermos aos construtores — mesmo que o padrão de nomenclatura recomendado e utilizado seja Create — e como os métodos podem ser virtuais, assim também são os construtores.

Mas, qual é a grande vantagem de utilizá-los?

Construtores Virtuais

Na documentação sobre Factory and Repository patterns do framework Synopse mORMot você encontrará o seguinte texto:

In fact, Delphi is ahead of Java or C#, since it allows virtual constructors to be defined. Those virtual constructors are in fact a clean and efficient way of implementing a Factory, and also fulfill SOLID principles, especially the Liskov Substitution Principle: the parent class define an abstract constructor on which you rely, but the implementation will take place in the overridden constructor.

No texto acima, eu sugiro apenas alterarmos a palavra “Delphi” por “Object Pascal”, visto que essa é uma feature da linguagem Object Pascal e não apenas da implementação do Delphi.

Na maioria das linguagens, o padrão Factory é implementado através de métodos (estáticos, abstratos ou virtuais) das classes e não através dos construtores. Esse é um dos motivos para o autor afirmar que o Delphi (Object Pascal) está a frente de C# e Java nesse quesito. Eu concordo.

Em Object Pascal podemos criar uma fábrica de objetos onde o tipo da classe original é a própria fábrica.

Pense no modelo clássico implementado em várias linguagens. Por exemplo, teríamos uma entidade principal TFoo e uma fábrica TFooFactory, que retorna classes-filhas da entidade principal. É importante lembrar que TFoo deveria implementar alguma Interface relacionada ao domínio, porém isso é irrelevante para o entendimento do problema.

O código principal iria utilizar a fábrica para ter instâncias de TFoo. A fábrica, no entanto, poderia retornar instâncias de novas classes-filhas, herdadas de TFoo e isso seria transparente para o código principal. Essa é uma das features que queremos ao utilizarmos uma fábrica.

Mas, primeiro teríamos que criar a fábrica para que ela retornasse as instâncias que realmente necessitamos.

Em Object Pascal não precisamos de uma classe específica para ser a fábrica de objetos. Nós podemos ter variáveis/argumentos do tipo classe e, dessa maneira, podemos passar diretamente a classe que deve ser utilizada para criar a instância; sem intermediários.

Imagine que temos uma simples library (lib) que soma 2 números. Essa lib tem uma classe default para fazer a soma, mas ela permite que a classe seja customizada, lembrando muito o padrão Strategy.

No exemplo acima temos a classe TLibCalc que representa a lib. No construtor podemos customizar a classe que representa o algoritmo da soma, caso contrário a lib irá utilizar a classe TSum padrão.

A classe TSum é simples. Ela soma dois inteiros. Mas repare que seu construtor é virtual.

O próximo passo é criar um programa de teste.

A saída do programa será: Result is 8.

Se tudo estiver funcionando por aí, vamos aos próximos passos:

  1. criar nossa própria classe para somar 2 números
  2. alterar o programa, customizando a lib

No código acima foi implementado uma nova classe TMySum e inicializamos a lib TLibCalc.Create(TMySum); com essa classe.

Execute o programa e veja o resultado.

Não foi necessária nenhuma fábrica. Nenhum “registro de classes” também foi necessário. Implementamos um padrão utilizando apenas classes simples da linguagem.

Finalmente, a linguagem Object Pascal é tão simples que bastou utilizarmos uma instância de classe contendo construtores virtuais para instanciar a classe correta.

Conclusão

Em Object Pascal não é necessário termos fábricas; a classe customizada é a própria fábrica.

Até onde eu sei, não existe essa feature em nenhuma linguagem mainstream, apenas em Object Pascal.

Com essa feature não é necessário criar classes de fábrica apenas para inicializar nossos verdadeiros objetos. Teremos menos classes, menos objetos, menos métodos, menos uso de memória, mais eficiência e simplicidade.

Até logo.

Posts Relacionados

  • Memória Segura Utilizando Instâncias de Interfaces

  • Classes Mutáveis vs Objetos Imutáveis

  • Implementando Interfaces Utilizando Diferente Assinaturas de Métodos

  • Usando Paths ao invés de Diretivas de Compilação

  • Trabalhando com Exceções em Requisições HTTP

  • Tipo object Continua Vivo

  • Array de Objetos

  • Variáveis Locais Deveriam ter Nomes Curtos

  • Como Dividir e Organizar o Código em Formulários com Muitos Widgets

  • Pascal Deveria ser Modernizado?