Fala ai Radizeiros e Radizeiras, tudo bem com vocês?
Mais um post aqui de nossa série de generics, e claro, é um maior prazer em poder compartilhar com vocês todo o conhecimento.
Nos últimos posts, nós vimos como trabalhar com genéricos na classe, criamos uma classe com um tributo genérico, vimos como preencher uma lista utilizando um enum, e claro através de generics para transformar um enum em qualquer lista.
Agora iremos ver um outro ponto que é muito legal, como é possível utilizar generics que não seja somente na construção da classe, podemos ter uma classe que não tenha um atributo genérico, mas em um método dela tem um atributo genérico.
Vamos simular um recurso muito legal que diversas outras linguagens tem, e claro, o Delphi também possui esses recursos, mas ele não é tão abrangente para qualquer tipo, então iremos criar um atributo genérico para fazer o famoso operador ternário, com em outras linguagens, por exemplo o PHP, que tem o “IIF”, e ele é muito legal e muito utilizado.
Então o que iremos fazer aqui agora, vamos pegar um projeto simples em VCL, coloca um botão no formulário.
Agora iremos criar uma classe que iremos chamar de TUtils, essa classe não tem nenhum atributo genérico, e dentro dessa classe iremos criar um class function, observe como está essa nossa classe no código logo abaixo.
TUtils = class class function IIF<T>(Condition : Boolean; T1, T2 : T) : T; end;
Nós criarmos um operador ternário IIF, que irá fazer o operador ternários de qualquer tipo que formos trabalhar.
Então você pode observar que esse método recebeu um tipo genérico, e você pode ver um detalhe, o genérico não está na classe, ele está no método, e nele passamos três parâmetros, um parâmetro que é o condicional, é o que ele irá utilizar para fazer a condição, e ele é do tipo booleano, pois a condição tem que ser, se for verdadeiro faça isso, se for falso, faça aquilo, e temos parâmetros do tipo genérico, e o seu retorno também é um genérico.
Mas talvez você esteja se perguntando, quando isso é usado, e em que situação isso é usado?
Você vai ver já já…rsrs
Nesse nosso método iremos implementar algumas linhas de código.
class function TUtils.IIF<T>(Condition: Boolean; T1, T2: T): T; begin if Condition then Result := T1 else Result := T2; end;
Você pode está olhando esse código e achar, para que criar uma classe para fazer isso, eu te digo uma coisa, é para você evitar de ficar reescrevendo código, viu essas 4 linhas que nós criamos com o if, se nós tivéssemos esse operador ternário genérico, todas as vezes que quisesse fazer uma validação, atribuir uma variável, por exemplo, teríamos que fazer esses IFs, e com o operador ternário não precisamos disso.
Dentro desse botão que colocamos no formulário, iremos testar esse nosso operador ternário.
procedure TForm1.Button1Click(Sender: TObject); var aux : String; begin aux := TUtils.IIF<String>((Edit1.Text <> ''), Edit1.Text, 'Favor informe um valor'); ShowMessage(aux); end;
Observe que criei uma variável do tipo string, e só será atribuído algum valor a essa variável se o Edit não for vazio, se ele for vazio eu atribuo um valor default.
Você viu que se eu não tivesse o operador ternário teria que fazer um if e ficar poluindo meu código?
Vamos testar para ver como irá se comportar nosso exemplo com o operador ternário?
Se deixarmos o Edit com informação ele irá mostrar na tela o valor que está no Edit que foi atribuído para a variável aux.
Agora se não atribuirmos nenhum valor ao Edit, temos que receber na tela a mensagem do valor default que colocamos no código.
Muito legal né?
Você pode utilizar isso que acabamos de criar para qualquer coisa agora, porque ele está com um tipo genérico.
Vamos fazer um outro exemplo agora?
Vamos criar uma classe de produtos com algumas informações.
TProduto = class private FDescricao: String; procedure SetDescricao(const Value: String); published constructor create; property Descricao : String read FDescricao write SetDescricao; end; ... constructor TProduto.create; begin FDescricao := 'Produto genérico'; end; procedure TProduto.SetDescricao(const Value: String); begin FDescricao := Value; end;
Observe que dentro do método construtor desse nessa classe eu atribui um valor default para a propriedade descrição, ou seja, se eu instanciar a classe e não mexer no atributo Descrição ela irá vai ser “Produto genérico”, se eu mexer é outra história.
Irei colocar um outro botão no formulário, para podermos trabalhar essa nossa classe de produto.
procedure TForm1.Button2Click(Sender: TObject); var Prod1, Prod2, Prod3 : TProduto; begin Prod1 := TProduto.create; Prod1.Descricao := 'Laranja Pera'; Prod3 := TUtils.IIF<TProduto>(Assigned(Prod1), Prod1, TProduto.create); ShowMessage(Prod3.Descricao); end;
Observe que nós instanciamos o Prod1, passamos para o Prod3 o operador ternário, passamos para o tipo genérico nossa classe TProduto, isso que é legal pois no ifThen da classe SysUtils do Delphi não tem, ele só trabalha com string, verificamos se o Prod1 foi instanciado, e caso ele tenha sido instanciado ele terá que me passar o valor “Laranja Pera” que atribuímos a propriedade Descricao, caso ao contrário ele irá receber o valor padrão.
Vamos compilar nosso exemplo e ver como será o seu comportamento?
Viu que legal, a nossa variável Prod3 está com uma condicional que diz se ele vai ser um clone do Prod1, caso esteja instanciado, se não, ai é instanciado um objeto novo, viu como é legal o que conseguimos fazer?
Agora o Prod2 não é instanciado, como fizemos com o Prod1, então irei substituir Prod1 por Prod2 e vamos ver o que irá acontecer?
Essa nossa condição tem que ser falsa, então ele tem que me retornar um novo objeto para de produto para Prod3, se ele está retornando um novo objeto ele irá pegar o nome default e atribuir para Prod3.
Olha que show, ele me retornou “Produto Genérico”, ta ai funcionando o nosso operador ternário.
Muito fácil, e muito legal de fazer, e claro, graças ao recurso de generics, agora você já pode testar qualquer condição, que te retorne qualquer tipo de objeto.
Essa é apenas mais uma das grandes coisas que podemos fazer com generics.
Esse treinamento irá lhe ensinar tudo sobre Generics no Delphi, lhe guiando pelos principais conceitos e recursos disponíveis sobre essa feature fantástica do Delphi, aprenda a criar códigos maleáveis, de fácil adaptação e mudanças para ter códigos de alta performance utilizando o que o Delphi tem de melhor
CLIQUE AQUI E SAIBA MAIS SOBRE O CLUBE DOS PROGRAMADORES DELPHI