Fala ai Radizeios e Radizeiras, tudo bem com vocês?
Temos evoluído a cada post não é verdade?
Creio que você já deve estar utilizando os generics em seus projetos.
Agora se você ainda não está utilizando generics dentro dos seus projetos, você está perdendo muito tempo escrevendo muitas linhas de códigos.
Como você pode ter observado, e como eu tenho falado bastante aqui na série sobre generics, que você pode reduzir muito as linhas de códigos utilizando generics.
O Delphi foi criado no ano de 1995, e atualmente no ano de 2020, no ano que é escrito esse post, você ainda não usa interfaces dentro do seu software.
Mas você pode está dizendo que já utiliza interfaces, onde você coloca o form e trabalha nele colocando os componentes, tendo maior cuidado para deixar sua interface bonita.
Não é esse tipo de interface que estou dizendo!
São as interfaces a nível de programação.
Você já deve ter ouvido muitos programadores dizerem, “Não programe para uma classe, programe orientado a interface”.
Exatamente isso que quero mostrar para vocês aqui nesse post.
Se você ainda não sabe o que é interface, aqui no blog e em diversos dos meus treinamentos tenho falado sobre muito, e utilizo bastante as interfaces.
E no post de hoje nós vamos descobrir como criar interfaces genéricas.
Vamos lá?
Isso mesmo que você viu, é possível criar interfaces genéricas dentro do Delphi.
E poderemos utilizar muito dentro de nossas classes.
No post de hoje eu não irei explicar a fundo o que é interface, como funciona, e para que serve.
Não, iremos ver como criar uma interface genérica, e como fazer para consumir essa interface genérica dentro da nossa classe.
Vamos ao nosso exemplo, mas desta vez, não teremos ele totalmente pronto…rsrsr
Iremos construir juntos um pequeno projeto utilizando interface genérica.
Tenho um projeto em branco, ou seja, um projeto novo em VCL.
Vamos dentro do editor de código do Delphi e iremos criar logo uma interface.
Type iQualquerCoisa<T> = interface procedure Add(Value : T); function Retorno : T; end;
Observe que coloquei um “i” na frente do nome da minha interface, isso é uma convenção, para identificar que ela é uma interface.
Como você já deve estar acostumado, quem acompanha a nossa série de generics já está acostumado em ver esses dois sinais, o de menor que <, e maior que >, onde em todas os generics nós utilizamos eles.
Dentro dessa nossa interface temos um método que retorno o tipo genérico.
Viu que legal, já criamos uma interface genérica.
Assim como a classe nós temos um tipo genérico, não sabemos que tipo é esse.
Vamos criar a classe qualquer coisa, que implementa essa nossa interface.
TQualquerCoisa<T> = class(TInterfacedObject, iQualquerCoisa<T>) FValue: T; procedure Add(Value : T); function Retorno : T; end; procedure TQualquerCoisa.Add(Value : T); begin FValue := Value; end; function TQualquerCoisa<T>.Retorno : T; begin Result := FValue; end;
Observe o “T” na frente do nome de nossa classe, também é utilizado por convenção, assim como o “i” para interface.
Quando criamos uma classe que implementa uma interface, é necessário que seja implementado também os métodos criados na interface, pois caso isso não seja feito é resultado num erro.
Todas as vezes que for criar uma classe que irá implementar uma interface, é de extrema importância também utilizar os métodos criados na interface, pois essa classe herda todas as assinaturas da sua interface.
Essa classe que implementa a interface, nada mais é que uma cada para expor algumas funcionalidades da nossa classe.
Então quando nós programamos orientado a interface, nós não deixamos ser exposto o que está na classe, só é exposto o que está na interface.
Por exemplo, a classe poderia ter mil métodos, mas se estou trabalhando orientado a interface, só se faz conhecido o método da interface, no nosso exemplo, o método Retorno.
Essa é umas das coisas legais que temos quando trabalhamos orientado a interfaces.
Dentro da implementação do método Retorno, como não sei qual é o tipo, só irei saber qual é esse tipo na hora de instanciar essa classe.
Por este motivo que temos a procedure Add, onde ela irá também receber um valor genérico, que ao ser instanciado teremos como trabalhar esse valor.
Observe que implicitamente foi feito um Get e Set.
Agora temos uma classe genérica implementando uma interface genérica.
Agora vamos ver como trabalhar com essa nossa classe.
Vamos colocar um botão no formulário.
Dentro desse botão iremos realizar algumas implementações.
procedure TForm2.Button1Click(Sender: TObject); var Aux : iQualquerCoisa<String>; begin Aux := TQualquerCoisa<String>.Create; end;
Lembra que falei no início?
Programe orientado a interface e não a classe.
Esquece a classe, iremos usar somente a interface agora, como você pode observar no código acima, onde eu criei uma variável do tipo da interface.
O tipo da interface iQualquerCoisa espera um generic.
Agora para atribuir um valor, é preciso instanciar a classe, como foi feito no código acima, onde eu chamado a variável Aux, instancio a classe já passando o tipo primitivo String.
Você pode estar se perguntando, mas não é para programar orientado a interface, e por que está declarando uma classe?
Realmente, mas essa classe que estou declarando é ela que implementa essa interface.
Então eu preciso de uma instância dessa classe para ter acesso a instância da interface.
Logo em seguido no código você consegue ver que consigo acessar todos os métodos dessa interface, e não tenho acesso aos métodos da classe.
Por exemplo, irei criar um novo método dentro dessa classe, e não na interface.
TQualquerCoisa<T> = class(TInterfacedObject, iQualquerCoisa<T>) ... procedure Duvida; ... procedure TQualquerCoisa.Duvida; begin //sem implementação end;
Se eu tentar compilar não terei erro algum, e esse método que criei somente na classe não encontra-se na interface.
E ao tentar usar a variável auxiliar, onde eu preciso acessar esse método novo criado dentro da classe, não irei poder acessar, pois lembra que essa classe implementa a interface, onde eu tenho acesso a instância dessa nossa interface.
Viu que esse método não existe, pois ele não faz parte da instância da interface, somente da classe.
Observe na imagem que ao instanciar o tipo genérico passando o tipo primitivo de String, onde a partir desse momento tanto o método Add quanto o método Retorno, recebem o tipo String.
Então agora eu posso simplesmente adicionar um nome para o método Add, e pegar o retorno desse valor adicionado.
procedure TForm2.Button1Click(Sender: TObject); var Aux : iQualquerCoisa<String>; begin Aux : TQualquerCoisa<String>.Create; Aux.Add('Thulio'); ShowMessage(Aux.Retorno); end;
Vamos compilar o projeto, e veja como já conseguimos trabalhar utilizando interfaces.
Prontinho, tá lá meu projeto rodando e funcionando bonitinho.
Talvez você que desconhece, pode estar se perguntando qual é a necessidade de se trabalhar orientado a interface.
Trabalhar com interfaces, você reduz o acoplamento, não irei entrar muito afundo aqui agora não, pois o mérito aqui é saber como utilizar os generics dentro das interfaces.
Muito simples trabalhar orientado a interface.
Simplesmente é criado uma interface genérica, e atribui essa interface genérica a uma classe que implementa essa interface.
Muito fácil não é?
Viu como podemos utilizar generics em diversas implementações dentro do nosso código?
Ainda mais quando programamos orientado a interface, utilizo muito no meu dia a dia.
E creio que sua cabeça deve estar fervendo, pois são inúmeras possibilidades que você consegue ter na utilização de interfaces, e ainda mais, na utilização de generics.
Espero que você tenha gostado dessa nossa série, e tenha curtido cada post, tenho trabalhado constantemente em pode levar conteúdos de qualidade, e claro, conteúdos que você possa utilizar no seu dia a dia.
E caso você tenha interesse de conhecer mais sobre generics acessa o nosso portal do CLUBE DE PROGRAMADORES EM DELPHI, onde você não só terá conteúdos relacionados aos generics, mas uma quantidade enorme de conteúdos que poderá lhe ajudar muito no seu dia a dia, é uma verdadeira NETFLIX para os programadores Delphi.
CLIQUE AQUI E SAIBA MAIS SOBRE O CLUBE DOS PROGRAMADORES DELPHI