Groovy 如何将对象上的元类还原为原始类定义
我一直在尝试在新对象上创建临时替代,然后删除对象本身的替代。我不确定这是否可以做到,但以下是我迄今为止所做的尝试Groovy 如何将对象上的元类还原为原始类定义,groovy,metaprogramming,Groovy,Metaprogramming,我一直在尝试在新对象上创建临时替代,然后删除对象本身的替代。我不确定这是否可以做到,但以下是我迄今为止所做的尝试 // 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 cons
// 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()
很抱歉没有提出一个非常具体的问题,因为我不知道在这个特定领域有什么可能。我喜欢我的代码不起作用的原因,以及使它起作用的替代方案。对您的策略进行一个小的修改将是富有成效的。对对象而不是类使用
元类
// 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()
,而不是对象本身。这可能是每个实例的元类问题。。。Validator.metaClass=null将验证程序类的全局元类设置为默认值。但是这里的验证器实例是Groovy类,因此在实例本身中存储对元类的单独引用。对该实例的调用不会进行全局元类的查找,而是使用每个实例的元类(实例本身中存储的引用)。因此,validator.metaClass=null是重置此AFAIK的唯一方法,在Grails单元/集成测试的上下文中,只需将元类
设置为null,就可以恢复原始元类,这样做有效吗?@Dónal设置validator
(类)的元类会使任何新对象都没有覆盖,但在我的例子中,我正在处理一个已经构建的实例。将验证程序的元类设置为(对象)没有任何作用。啊,我错了,将元类设置为null确实有效,尽管您必须将类的元类和对象的元类都设置为null。我尝试了每一种,但单独使用它们不起作用,但设置它们两种都起作用!感谢@DónalYes的启发,我已经尝试过这个方法,这确实会起作用,但是在我的例子中,验证器的构建很复杂(不使用DI),所以我在第一个集成点没有对对象的引用。这不重要。它可以尽可能地懒散地完成。您将在某个时间点获得validator对象,在该时间点上,您可以在newvalidator()之后立即执行答案中显示的任何操作。我不确定我是否理解了其他情况。事实上,验证器接收对多个对象的引用,这些对象还不可用,创建成本很高,并且在构造函数中会产生令人讨厌的副作用。