解释" this.type"作为各种API方法的返回类型

时间:2014-08-18 14:41:38

标签: scala

我正在查看Promise[T]包中scala.concurrent特征的源代码。 所以这里是我需要你帮助的方法声明:

trait Promise[T] {
 ....
 def complete(result: Try[T]): this.type =
 if (tryComplete(result)) this else throw new IllegalStateException("Promise already completed.")
 ....
}

我真的不明白如何将this.type解释为complete方法返回类型。为什么不简单的返回类型可能是Promise[T]

很抱歉,如果我的问题对某些人来说太简单了,我只是在学习这些东西。

2 个答案:

答案 0 :(得分:2)

this.type在路径相关的上下文中是必需的:

scala> class A { class B; def f(b: B): A = this }
defined class A

scala> val a1 = new A; val b1 = new a1.B; val a2 = new A
a1: A = A@721f1edb
b1: a1.B = A$B@5922f665
a2: A = A@65e8e9b

scala> a1.f(b1)
res6: A = A@721f1edb

scala> a2.f(b1)
<console>:12: error: type mismatch;
 found   : a1.B
 required: a2.B
              a2.f(b1)
                   ^

路径依赖意味着编译器知道类型属于一起。在上面的示例中,我们可以看到new a1.B生成a1.B类型的值,而不仅仅是B。但是,这不起作用:

scala> a1.f(b1).f(b1)
<console>:11: error: type mismatch;
 found   : a1.B
 required: _2.B where val _2: A
              a1.f(b1).f(b1)
                         ^

问题是f的返回类型是A,它不再有关于路径依赖关系的信息。返回this.type会告诉编译器返回类型满足以下关系:

scala> class A { class B; def f(b: B): this.type = this }
defined class A

scala> val a1 = new A; val b1 = new a1.B; val a2 = new A
a1: A = A@60c40d9c
b1: a1.B = A$B@6759ae65
a2: A = A@30c89de5

scala> a1.f(b1).f(b1)
res10: a1.type = A@60c40d9c

答案 1 :(得分:2)

我怀疑原因是支持继承。

考虑这个简单的例子

trait Foo[A] {
  def foo: Foo[A] = this
}

trait Bar[A] extends Foo[A]

现在让我们试一试

scala> (new Foo[Int]{}).foo
res0: Foo[Int] = $anon$1@7f0aa670

scala> (new Bar[Int]{}).foo
res1: Foo[Int] = $anon$1@4ee2dd22

正如您所看到的,方法foo在两种情况下都返回Foo[Int],这是因为您在方法定义中返回了“硬编码”类型Foo[T]

如果您改为

trait Foo[A] {
  def foo: this.type = this
}

trait Bar[A] extends Foo[A]

然后返回的类型取决于您在foo上调用的实例:

scala> (new Foo[Int]{}).foo
res2: Foo[Int] = $anon$1@1391e025

scala> (new Bar[Int]{}).foo
res3: Bar[Int] = $anon$1@4142991e