Um das grandes passagens do livro Code Complete é sem dúvidas aquela que diz: “se uma linguagem não suporta nativamente uma determinada implementação, você deve então programar ‘para a linguagem’ e não ‘na linguagem’ “. O exemplo que o livro apresenta para essas limitações é justamente com relação ao Typesafe Enum, nossa dica Flex de hoje.
Os Enums são muito utilizados para evitar redundância de código e garantir o máximo de segurança nas aplicações. Além de serem excelentes objetos para se trabalhar com estados e tipos, eles também são parte essencial quando trabalhamos com o padrão de projeto State. Ele é muito utilizado também para limitar as opções de argumentos para determinados métodos. O problema é que diferente do Java 5 ou do ActionScript 2, o ActionScript 3 não suporta Enums e não permite usar o modificador privado no construtor das classes.
Suponha que temos um método que retorna a URL de uma imagem em 3 diferentes tamanhos: Pequeno, médio e grande. Para retornar o caminho dessa imagem passamos como argumento do método qual o tamanho que esperamos. Sem utilizar o Typesafe Enum poderíamos fazer conforme código abaixo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 <?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="application1_initializeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
private static const PEQUENO:String = "pequeno";
private static const MEDIO:String = "medio";
private static const GRANDE:String = "grande";
protected function application1_initializeHandler(event:FlexEvent):void
{
trace( retornaCaminhoImagem("texto qualquer") );
}
private function retornaCaminhoImagem(tamanho:String):String
{
var caminho:String;
switch(tamanho)
{
case PEQUENO:
{
caminho = "http://www.suaurl.com/imagem_pequena.jpg";
break;
}
case MEDIO:
{
caminho = "http://www.suaurl.com/imagem_media.jpg";
break;
}
case GRANDE:
{
caminho = "http://www.suaurl.com/imagem_grande.jpg";
break;
}
default:
{
caminho = "[ERRO]";
}
}
return caminho;
}
]]>
</fx:Script>
</s:Application>
O problema no código acima é que podemos passar como argumento do método “retornaCaminhoImagem()” qualquer string:
1 trace( retornaCaminhoImagem("texto qualquer") );
Para resolvermos o problema acima vamos criar uma classe que implementa o padrão Typesafe Enum:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package enum
{
public class ImageSizeEnum
{
public static const PEQUENO:ImageSizeEnum = new ImageSizeEnum("pequeno");
public static const MEDIO:ImageSizeEnum = new ImageSizeEnum("medio");
public static const GRANDE:ImageSizeEnum = new ImageSizeEnum("grande");
private var _tamanho:String;
private static var _instance:Boolean = false;
// Bloco estático
{
_instance = true;
}
public function ImageSizeEnum(tamanho:String)
{
if(_instance)
{
throw new Error("Você não pode instanciar um Typesafe Enum");
}
_tamanho = tamanho;
}
public function toString():String
{
return this._tamanho;
}
}
}
Repare no bloco estático que criamos, ele será excutado assim que a classe for carregada na memória, portanto antes do construtor da classe ser chamado e depois que todos os membros estáticos forem criados.
Agora crie um novo método chamado “retornaCaminhoTypesafeEnum()”:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 private function retornaCaminhoTypesafeEnum(tamanho:ImageSizeEnum):String
{
var caminho:String;
switch(tamanho)
{
case ImageSizeEnum.PEQUENO:
{
caminho = "http://www.suaurl.com/imagem_pequena.jpg";
break;
}
case ImageSizeEnum.MEDIO:
{
caminho = "http://www.suaurl.com/imagem_media.jpg";
break;
}
case ImageSizeEnum.GRANDE:
{
caminho = "http://www.suaurl.com/imagem_grande.jpg";
break;
}
default:
{
caminho = "[ERRO]";
}
}
return caminho;
}
Para utilizá-lo faça:
1 trace( retornaCaminhoTypesafeEnum(ImageSizeEnum.GRANDE) );
Faça alguns testes, tente instanciar nosso Enum para criar um novo tipo:
1 var enum:ImageSizeEnum = new ImageSizeEnum("novo_tipo");
Como resultado você deve ter recebido um erro em tempo de execução com a mensagem: “Você não pode instanciar um Typesafe Enum”.
Agora tente passar uma string qualquer como argumento do método “retornaCaminhoTypesafeEnum()”:
1 trace( retornaCaminhoTypesafeEnum("novo_tipo") );
Você deve ter visto um erro em tempo de compilação uma vez não ser possível passar como argumento do método uma string quando ele espera o tipo “ImageSizeEnum”.
Bom galera espero que tenham gostado. Veja aqui um projeto de exemplo.
Até a próxima!




