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,

Leave a Reply

Web Analytics