【问题标题】:Possible to override members of an inner trait?可以覆盖内部特征的成员吗?
【发布时间】:2013-12-03 14:33:47
【问题描述】:

在扩展外部类时是否可以覆盖内部特征的成员?喜欢

class Foo {
  trait Bar {
    def bar = Set("a", "b")
  }

  class Baz extends Bar
  object Baz {
    def apply() = new Baz
  }
}

我能否以任何形式创建 fFoo 实例,例如 f.Baz().bar == Set("c", "d")

澄清Foo 类是给定的,我无法更改。它调用Baz(),所以我也无法更改它。因此,可能无法在 BarBaz 中改进覆盖内容?

【问题讨论】:

    标签: scala inheritance inner-classes overriding


    【解决方案1】:

    您可以尝试创建一个父类是原始 Baz 的新类。然后重写bar的定义:

    val f = new Foo { 
      class Baz2 extends Bar { override def bar = Set("c") } 
      object Baz2 { 
       def apply() = new Baz2(); 
      }
    }
    

    这将为您提供一个新条目:f.Baz2().bar,它将为您提供 Set("c")。您仍然可以访问原始 Bar 特征的成员。

    据我所知,您不能覆盖内部类的对象。所以很难在那个类上生成新的特征。

    【讨论】:

    • 问题是Foo的实现实例化了Baz,所以不会注意到不同的子类
    • 我不确定我是否遵循...您指的是哪个子类?在上面的实现中,你得到了所有原始的 Baz,但是覆盖了一个特定的方法。你能澄清一下你需要做什么吗?
    【解决方案2】:

    编辑:

    根据您的说明,您似乎想要做的是覆盖对象Baz。这通常是不可能的,但是如果您使用实验性编译器标志-Yoverride-objects,您可以执行以下操作:

    class SubFoo extends Foo {
      class Baz extends super.Baz {
        override def bar = Set("c", "d")
      }
      override object Baz { 
        def apply() = new Baz
      }
    }
    

    有了这个(new SubFoo).Baz().bar == Set("c", "d")。但是,如果您的子类实例类型为 Foo,您可能会遇到运行时类转换异常,如以下错误:SI-6525

    原答案:

    您需要在 Foo 类中有一个可覆盖的工厂方法,该方法可以返回您的 Bar 子类。然后在您的 Foo 子类中,返回一个 Bar 子类,并覆盖 bar 方法。例如:

    class Foo {
      trait Bar {
        def bar = Set("a", "b")
      }
    
      def createBar = new Bar {}
    }
    
    class SubFoo extends Foo {
      override def createBar = new Bar { override def bar = Set("c", "d") }
    }
    
    scala> var foo: Foo = new Foo
    foo: Foo = Foo@5ea0e5b9
    
    scala> foo.createBar.bar
    res15: scala.collection.immutable.Set[String] = Set(a, b)
    
    scala> foo = new SubFoo
    foo: Foo = SubFoo@7f8d5474
    
    scala> foo.createBar.bar
    res16: scala.collection.immutable.Set[String] = Set(c, d)
    

    【讨论】:

    • 问题是,Foo 是给定的,不是我设计的(它实际上是 Scala 编译器框架的一部分)
    • 也许您可以进一步阐明约束条件。我已经展示了如何在扩展外部类时对内部特征进行子类化。但是,要使用子类化的内部特征,您需要实例化它。如果你不能用你的新特性覆盖实例化原始特性的代码,那么你真的无能为力。但这与它是一种内在特征这一事实没有任何关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 2021-03-02
    相关资源
    最近更新 更多