【问题标题】:Type of 'return this' in a Groovy @MixinGroovy @Mixin 中的“return this”类型
【发布时间】:2011-11-06 01:12:22
【问题描述】:

我有一个 mixin 类,它为不共享共同遗产的不同类型捆绑了功能。使用 @Mixin 注释应用混合,因此在编译时处理。

一些 mixin 方法返回 this 作为方法调用的结果。问题是 this 是混合类型而不是基类的类型。当我想在应用程序的其余部分中键入时,会抛出 ClassCastException,说明无法将混合类型强制转换为基本类型。

在下面的示例代码中,return this 返回一个 AMixin 类型的对象,而不是一个 BaseClass 类型的对象。

如何让return this 返回 BaseClass 类型的对象而不是 AMixin 类型的对象?

class AMixin {

  def getWhatIWant(){
    if(isWhatIwant){
      return this
    } else {
      getChildWhatIWant()
    }
  }

  def getChildWhatIWant(){
    for (def child in childred) {
        def whatIWant = child.getWhatIWant()
        if (whatIWant) {
            return whatIWant
        }
    }
    return null
  }
}


@Mixin(AMixin)
class BaseClass {
  boolean isWhatiWant
  List<baseClass> children
}

【问题讨论】:

    标签: groovy mixins


    【解决方案1】:

    我创建了 Base 类,将类别添加到 AMixin 类中,BaseClass 扩展自 Base.....(http://groovy.codehaus.org/Category+and+Mixin+transformations)

    我在 GroovyConsole 中执行了这个

    BaseClass@39c931fb

    class Base {
         boolean isWhatIwant
         List<BaseClass> children
    }
    
    @Category(Base)
    class AMixin {
    
      def getWhatIWant(){
        if(isWhatIwant){
          return this
        } else {
          getChildWhatIWant()
        }
      }
    
      def getChildWhatIWant(){
        for (def child in children) {
            def whatIWant = child.getWhatIWant()
            if (whatIWant) {
                return whatIWant
            }
        }
        return null
      }
    }
    
    
    @Mixin(AMixin)
    public class BaseClass extends Base {
    
    }
    
    def b = new BaseClass(isWhatIwant:true)
    println b.getWhatIWant()
    

    只编辑一个 DummyClass。我知道它的工作原理很尴尬......我确信Guillaume Laforge 可以回答这是如何工作的......

    class DummyClass {
    
    }
    
    @Category(DummyClass)
    class AMixin {
    
      def getWhatIWant(){
        if(isWhatIwant){
          return this
        } else {
          getChildWhatIWant()
        }
      }
    
      def getChildWhatIWant(){
        for (def child in children) {
            def whatIWant = child.getWhatIWant()
            if (whatIWant) {
                return whatIWant
            }
        }
        return null
      }
    }
    
    
    @Mixin(AMixin)
    public class BaseClass extends DummyClass {
         boolean isWhatIwant
         List<BaseClass> children
    }
    
    def b = new BaseClass(isWhatIwant:true)
    println b.getWhatIWant()
    

    【讨论】:

    • @Category(Base) 注解对 Mixin 类有什么影响?如果我有多个基类,我认为这是不可能的,例如BaseA、BaseB 和 BaseC。
    • 不,你不能在 Mixin 中有多个类别的基类,但是你可以有多个相同类别的 mixin,这有助于有一种“多层次”。 @Category 在 groovy 中用于元编程和扩展类。
    • 但我为什么要扩展 AMixin 类,并将 BaseClass 作为类别?我只需要在 BaseClass 中提供 AMixin 功能。
    • 这有点冗余,但是使用@Category 属性,您告诉AMixin 类它将使用该对象,并且只能对这种对象进行“混合/扩展”。我不是真正了解元编程如何在幕后工作的 groovy 大师......我只是试图回答你的问题...... :) 我只是使用该类作为 Dummy 来编辑答案全部留在基类中
    【解决方案2】:

    我刚刚遇到了同样的情况。我通过将具体类中的“this”设置为具体类中的私有变量“me”并在 Mixin 类中返回“me”来解决它。例如:

    class MyMixin {
        def mixinMethod() {
            // do stuff
            return me
        }
    }
    
    @Mixin(MyMixin)
    class MyConcreteClass {
        private MyConcreteClass me
        MyConcreteClass() {
            me = this
        }
    }
    

    我觉得它有点笨拙,但我认为它比其他解决方案简单得多。我个人需要在多个类中使用相同的 Mixin 的能力,如果你不能将多个类别分配给单个 Mixin 类,听起来这个其他提议的解决方案将不允许这样做。

    【讨论】:

    • 此解决方案有效,谢谢。因为我的 Mixin 必须被初始化,所以我选择用 this 调用这个方法 init(this),所以我可以通过这种方式将“真实”的 this 传递给 Mixin——对我来说似乎更干净一些。但是,这两种解决方法都存在一些问题,它们不应该是必需的。
    • 这种方法解决了我的问题,但正如 Ice09 已经说过的那样,这种解决方法感觉不对。
    猜你喜欢
    • 2010-09-30
    • 2013-06-02
    • 2011-01-30
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    相关资源
    最近更新 更多