quarta-feira, 5 de março de 2008

Melhorando o “try()” do Ruby, a maneira “Groovy” [parte 2]

Vou pedir perdão ao meu amigo Urubatan, que publicou um artigo de mesmo nome.

class Omega
def doIt
puts "ola"
self
end
end

class NullableClass
def method_missing(*x)
self
end
end

class Object
def existe?
self
end
end

class NilClass
def existe?
NullableClass.new
end
end

xyz = Omega.new
xyz . existe? . doIt . doIt

abc = nil
abc . existe? . doIt . doIt


Estou em duvida sobre o nome do metodo, por enquando fica existe? mesmo.

O que isso faz? Imagine que vc tem uma variavel ou atributo de classe que pode ser nil. Se for nil ela vai lançar um um erro em tempo de execução quando vc for tentar chamar algum método que a NilClass não possua (o que geralmente acontece, é semelhante ao NullPointerException do java).

Eu poderia resolver isso alterando o method_missing da NilClass, porém alguns scripts podem estar esperando erros desse tipo. Decidi então criar um método que, para qualquer objeto, retorna ele mesmo (self). Caso seja nil, ele vai retornar um NullableClass (outro nome infeliz, não tenho nenhuma ideia melhor) que simplesmente retorna ele para qq método requisitado.

IMHO pode ser o suficiente quando queremos fazer um teste simples: o objeto é nil? então não faz nada.

Se alguem achar isso util por favor me avise :)

Ah sim, a execução do script acima resulta em:
ola
ola

Um comentário:

Urubatan disse...

como eu disse quando tu postou este comentário no meu blog, este teu esquema não resolve o problema de aninhamento de objetos, por exemplo

@person.company.manager.name
se eu digitar
@person.existe?.company.manager.name
e company for nil vai explodir tudo
e um .existe?. depois de cada objeto vai ficar gigante e pior do que o try na minha opinião :D