A metaprogramação em linguagens dinâmicas
Vamos imaginar que gostaríamos de “adicionar comportamentos específicos” aos nossos objetos já escritos. Neste caso, usando a pura, tradicional, cafona e obsoleta orientação a objetos, estaríamos travados e acabaríamos por optar por uma composição de objetos, ou quem sabe uma generalização, certo? Uma das maiores vantagens (e perigos caso o programador seja na verdade um macaco de código), é o uso da metaprogramação. A metaprogramaçao nos permite exatamente isto, adicionar funções, e alterar o “esqueleto comportamental” de classes e objetos, por exemplo.
Para uma classe onde temos nosso cachorro, que anda:
class Dog {
def walk() {
println “walking…”
}
}
se quisessemos definir um método para que ele latisse em runtime, faríamos da seguinte maneira:
def dog = new Dog()
dog.walk() //walking…
//Neste ponto, se fizermos a chamada dog.bark() teremos
//uma exception por estarmos chamando um método inexistente.
//Poderíamos contornar o erro com a implementação do methodMissing
//como dito no outro post, ou então da seguinta maneira
dog.metaClass.bark = {
println “au.”
}
//Pronto, após isto, é só latir
dog.bark() //au.
Poderíamos também trabalhar com parâmetros da função
dog.metaClass.bark = { vezes ->
vezes.times {
println “au.”
}
}
dog.bark(5)
//au.
//au.
//au.
//au.
//au.
Neste caso, definimos o comportamento do método bark() em runtime, para um objeto já existente. Se quisessemos agora, unir os comportamentos de um objeto, em outro, poderíamos usar o recurso de mixin de objetos, que traz as definições de métodos e funçoes de um objeto para outro. Tendo a definição de um pato, onde:
class Duck {
def quack() {
println “quack!”
}
}
Fica fácil fazer com que o pato ande como um cachorro! (absorvendo a função definida na classe Dog)
def duck = new Duck()
duck.quack() //quack!
//dedo de deus
duck.metaClass.mixin Dog
duck.walk() //walking
É isso aí.
[]s,
Comments(0)