Last active
December 19, 2015 10:09
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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