Páginas

terça-feira, 9 de outubro de 2012

[Objective-C] Uso de selectors

Objective-C é uma linguagem feita para tornar as coisas simples. Tão simples que para quem não está acostumado pode soar como (coxa) excessiva.

Sabe todo aquele blah blah blah de alta coesão e baixo acoplamento? Então, várias features nativas do Objective-C podem te ajudar a alcançar estas diretrizes da Engenharia de Software, no que diz respeito à Programação Orientada a Objetos (POO).

Neste post vamos falar sobre uma facilidade provida pela linguagem Obj-C, que são os selectors (seletores, na tradução livre).

Imagine que você cria um simples programinha com uma dezena de classes. Dentre essas classes temos a classe Formulário que é uma classe ligada a modelagem do sistema e sem ligação direta com o negócio e uma outra classe Carro que é ligada ao negócio.

Por "coincidência" as duas classes tem o método
-(void)setVisibility:(bool)visibility;
o qual permite esconder ou mostrar determinado objeto das classes. Até aí tudo bem, são classes distintas que não compartilham nenhuma herança (i.e. superclasses e interfaces protocolos).

Mas o que o Obj-C faz quando compila estas classes é o grande pulo do gato: O compilador gera um identificar único para cada método de uma classe. Este identificador do método é gerado baseado no seu nome e nos parâmetros que ele recebe, mas não leva em consideração a classe em que o método está inserido.

Neste caso, o compilador vai gerar o mesmo identificador do método para ambas as classes. Este identificador é conhecido como selector.

Neste momento o leitor indaga:
- Tá bom, eu tenho dois métodos em classes diferentes que tem o mesmo identificador, mas pra quê isso vai ser útil???
Respondo:
-Não sejais apressado, pequeno gafanhoto.

Em Obj-C é possível executar um método de um objeto através de seu seletor, ou seja, você não precisa conhecer a classe, ou a interface o protocolo que uma classe "implementa" para conseguir realizar uma invocação. Tudo que você precisa é saber qual o seletor daquele método.
Para o nosso exemplo teríamos o seguinte seletor:
SEL visibilitySelector = @selector(setVisibility:)
Agora, voltando ao exemplo, imaginemos que uma classe é responsável por esconder ou tornar visível os objetos que são apresentados, de acordo com o perfil de autenticação do usuário na aplicação. Essa classe não precisa de conhecer muita coisa, basta apenas ser capaz de executar o seletor nos objetos corretos.

Aqui vai um outro truque, para executar um seletor que recebe parâmetros, nos utilizamos a diretiva
-(id)performSelector:(SEL)sel withObject:(id)obj
, mas no nosso exemplo o parâmetro recebido pelo método é um tipo primitivo (booleano). Neste caso devemos encapsulá-lo em uma classe que possa ser reconhecida pelo método como um booleano.

A forma mais comum, para o caso do booleano, é encapsular em um número inteiro (NSNumber):
bool myBool = true; 
NSNumber *passedValue = [NSNumber numberWithBool:myBool];

Aí sim, podemos executar o seletor, passando o valor booleano dentro do objeto da classe NSNumber. Trabalhando desta forma conseguimos fazer com que a classe que faz a gestão da visibilidade dos objetos não seja acoplada com outras classes ou protocolos, tornado a vida do programador mais fácil.

PS: Tá bom, com reflection eu também consigo fazer alguma coisa parecida em java, apesar de ser muito mais burocrático.
PS2: Se ficou alguma coisa não inteligível é porque acabou meu café.

Nenhum comentário:

Postar um comentário