Skip to content

Instantly share code, notes, and snippets.

@lucastelnovo
Last active December 19, 2015 10:09
Show Gist options
  • Save lucastelnovo/5937964 to your computer and use it in GitHub Desktop.
Save lucastelnovo/5937964 to your computer and use it in GitHub Desktop.
Implementación de la clase 'Prototipo' for dummies. Hecha con 'withParams'. Very verbose. Full comments.
class Prototipo {
static init() {
Object.metaClass {
prototype = null
// La inicializo en null porque cuando redefino el constructor, ahi le digo que será un mapa.
dynamicProperties = null
// Property missing para setear.
propertyMissing = { String name, value ->
dynamicProperties[name] = value
}
// Property missing para gettear.
propertyMissing = { String name ->
if(dynamicProperties.containsKey(name)){
// Si la key ya fue seteada previamente, la devuelvo sin problemas.
return dynamicProperties["$name"]
}
/*
* Si no contiene esa key la propia variable, deberia ir a buscar a su prototipo
* en caso de que existiere.
*/
else if(prototype != null){
return prototype."$name"
/*
* Busca en el prototipo que posee sus properties y sus métodos previamente seteados.
*/
}
// Rompe porque la property no fue seteada previamente.
throw new MissingPropertyException(name, delegate.getClass())
}
methodMissing = { String name, args ->
try{
def bloque = delegate."$name"
/*
* Acá obtengo por ejemplo => " def bloque = a.suma = bloque "
* Entra por el setter de propertyMissing(name: suma, value = bloque).
* suma es: { operador3 , operador4 -> operador4 + operador3 + operador1 + operador2 }
* entonces, el valor de la variable "bloque" será justamente este bloque (closure).
*/
delegate.withParams(bloque, args)
/*
* Acá ejecuto el bloque con los argumentos que le
* son pasados a ese bloque (los argumentos del método,
* que son operador 3 y operador 4).
*/
}catch(MissingPropertyException e){
throw new MissingMethodException(name, delegate.getClass(), args)
}
}
/*
* Me guardo en la variable oldConstructor el constructor por defecto de la clase Object.
* Lo necesito para la creación de una nueva instancia.
*/
def oldConstructor = Object.metaClass.retrieveConstructor()
/*
* Redefino el constructor de la clase Object para que cada vez que haya una nueva instancia
* de un objeto, este posea su propio mapa de dynamicProperties.
*/
constructor = {
def newInstance = oldConstructor.newInstance()
newInstance.dynamicProperties = [:]
newInstance
}
withParams = { closure, Object... params ->
final Closure clonedClosure = closure.clone();
clonedClosure.setResolveStrategy(Closure.DELEGATE_FIRST);
clonedClosure.setDelegate(delegate);
clonedClosure.call(*params);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment