【问题标题】:Mixins in ScalaScala 中的 Mixin
【发布时间】:2011-10-23 14:06:13
【问题描述】:

我正在尝试在 Scala 中创建一个特征:

trait First {
  override def greet() {
    super.greet
    println("First")
  }
}

但是编译器说:

scala/scala_learning/traits_hierarchy.scala:3: error: value greet is not a member of java.lang.Object with ScalaObject
    super.greet
          ^

但是我想用这个特性扩展一些超类有方法 greet 的类......在 scala 中是否可能?

【问题讨论】:

    标签: scala


    【解决方案1】:

    虽然 scala 中有结构类型,但我认为您不能对任何具有 greet 方法的类型执行此操作,而是针对特定 trait 或类中的 greet 方法。

    如果你想让你的例程改变一个尚未定义的例程,用 super 调用它,它必须标记为abstract override,而不是简单地覆盖。

    那就是

    trait Greeter { def greet }
    
    trait First extends Greeter {
      abstract override def greet = {
        super.greet
        println("Hi, I'm first")
      }
    }
    

    然后你就可以定义问候语了

    class StandardGreeter(greeting: String) extends Greeter {
      def greet = println(greeting)
    }
    

    请注意,First 是在不了解 StandardGreeter 的情况下定义的。你在新的类中混入

    class FirstGreeter(greeting: String) extends StandardGreeter(greeting) with First
    

    或者直接用

    创建实例
    new StandardGreeter("whatever") with First
    

    您可能想阅读this article

    【讨论】:

      【解决方案2】:

      我相信你可以用结构自我类型做到这一点:

      trait Foobar {
          this: { def greet() } => // self type
          def go() = greet()
      }
      class Barbar extends Foobar { def greet() = { println("hello") }}
      

      您正在定义 Foobar 只能扩展定义了方法 greet() 的类。使用 REPL:

      scala> trait Foobar { this: { def greet() } =>
           | def go() = greet()
           | }
      defined class Foobar
      
      scala> new Foobar()
      <console>:9: error: class Foobar cannot be instantiated because it does not conform to its self-type Foobar with AnyRef{def greet(): Unit}
                    new Foobar()
                    ^
      
      scala> class Barbar extends Foobar { def greet() = { println("hello") }}
      defined class Barbar
      
      scala> new Barbar().go
      hello
      

      然后你可以覆盖 Foobar 中的 greet 方法(但我不知道这个有什么用):

      trait Foobar {
          this: { def greet() } => // self type
          override def greet() = { println("mygreet") }
          def go() = greet()
      }
      class Barbar extends Foobar
      

      【讨论】:

      • 好的,但是 mixin 是从哪里来的呢?
      • @didierd FooBar 可以是trait
      • @Daniel。 Mayve对问题的理解。我认为关键是要打招呼 super.greet + 其他东西,这通常是一个抽象的覆盖。在这里,我们对可以混合的内容有结构性限制,这绝非易事,但我们可以做一些类似于抽象覆盖的事情吗?
      • @didierd。你是对的,我的意思是使用特质 Foobar 而不是类。您可能对 OP 是正确的。我们会等着看他说什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      • 2011-12-18
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      相关资源
      最近更新 更多