A linguagem Object Pascal possui uma feature que não existe em nenhuma outra linguagem mainstream do mercado.
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:
- criar nossa própria classe para somar 2 números
- 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.