我一直试图在新对象上创建TEMPORARY覆盖,然后删除对象本身的覆盖。我不确定是否可以这样做,但这是我迄今为止尝试过的。
// Say I have a class like:
class Validator {
boolean validate() { println "code here to return actual true/false"; false }
}
// I have two integration points one of them is Here before construction:
// First integration point:
// Save actual validate function
def realValidate = Validator.&validate
// Make new instances of Validator have the validate function hardwired to true
Validator.metaClass.validate { -> println "hardwired true"; true }
// Code I'd rather not modify
// Now some code executes which news up an instance and calls validate
def validator = new Validator()
validator.validate() // This correctly calls our override
// Second integration point.
// Without newing up a new Validator object, I'd like to remove the override.
Validator.metaClass = null
validator.metaClass.validate = Validator.&validate
// This throws "java.lang.IllegalArgumentException: object is not an instance of declaring class"
//validator.validate()
// So maybe I have to explicitly say:
realValidate.resolveStrategy = Closure.DELEGATE_FIRST
// But this still throws the same exception
//validator.validate()
// Perhaps if I tell my objects metaclass to forget about validate, it will bubble up and look for the method on its declaring class?
validator.metaClass.validate = { -> throw new MissingMethodException("validate", Validator.class, (Object[])[], false) }
// This throws MissingMethodException: No signature of method: Validator.validate() is applicable for argument types: () values: []
// Possible solutions: validate(), wait()
//validator.validate()
抱歉没有超级具体的问题,因为我不知道在这个特定领域有什么可能。我既喜欢我的代码不起作用的原因,也喜欢使其成功的替代方案。
答案 0 :(得分:0)
对您的策略进行一些小修改将是富有成效的。在对象上使用metaClass
而不是Class。
// Say I have a class like:
class Validator {
boolean validate() { println "code here to return actual true/false"; false }
}
def validator = new Validator()
// mark that the pointer is on object instead of class
def realValidate = validator.&validate
validator.metaClass.validate { -> println "hardwired true"; true }
validator.validate() // This correctly calls our override
// Second integration point.
// DO NOT NEED THIS
// validator.metaClass = null
// Assign the method pointer to validate to call original validate
validator.metaClass.validate = realValidate
validator.validate()
您的方法无效,因为您在类引用的validate()
上覆盖metaClass
而不是对象本身。
答案 1 :(得分:0)
这可能是每个实例的元类问题... Validator.metaClass = null会将Validator类的全局元类设置为默认值。但是这里的验证器实例是一个Groovy类,因此在实例本身中存储了对元类的单独引用。使用该实例的调用将不会查找全局元类,而是使用每个实例元类(存储在实例本身中的引用)。因此,validator.metaClass = null是重置此
的唯一方法