【问题标题】:scala self type trait instantiationscala自我类型特征实例化
【发布时间】:2018-06-07 03:22:52
【问题描述】:

Scala 中的特征类似于 Java 中的接口或抽象类。因此,不可能直接从特征中获取实例。但是,我找到了一种实例化特征的方法。这是我的工作:

trait B {
  def bId = 1
}

trait A { self: B =>
  def aId = 2
}

val a = new A with B // The type of a is "A with B", a's value is $anon$1@6ad16c5d

以及以下内容:

trait User {
  def name: String
}

trait DummyUser extends User {
  override def name: String = "foo"
}

trait Tweeter { self: User =>
  def tweet(msg: String) = println(s"$name: $msg")
}

val t = new Tweeter with User // This doesn't compile
val t = new Tweeter with User with DummyUser // This does work!
// t: Tweeter with User with DummyUser = $anon$1@72976b4
t.tweet("hello")  // result is: "foo: hello"

这两段代码都在 Scala 2.12 上运行。在他们所有人中,只有特质!根本没有课。

特质如何以这种方式发挥作用?

【问题讨论】:

  • 实际上比这简单得多。 new B {}

标签: scala


【解决方案1】:

这个实例化类似于 JavaAnonymous Classes 实例化,所以当new Tweeter with User 它实际上是为Tweeter with User 创建一个新的匿名实例 匿名类。

new Tweeter with User 无法编译,因为它失去了 name 方法的实现。实际上你需要像这样实现它:

  val t = new Tweeter with User {
    override def name: String = "hello world"
  }

对于new Tweeter with User with DummyUser,您只需将其声明为new Tweeter with DummyUser,因为DummyUserUser 的子类型。

Scala 中有一个cake pattern 说明如何使用self 类型 来实现依赖注入

【讨论】:

  • 那么“new A with B”只是“new Object extends A with B”的语法糖吗?或者,比如使用案例类?
  • @JeffXu 是的,它从AB 创建了一个extends 的新类(匿名类)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 2018-06-02
  • 1970-01-01
相关资源
最近更新 更多