define方法返回扩展它的类的类型

Aar*_*ken 22 types scala

我希望能够做到这样的事情:

trait A {
  def f(): ???_THE_EXTENDING CLASS
}
class C extends A {
  def f() = self
}
class D extends A {
  def f() = new D
}
class Z extends D {
  def f() = new Z
}
Run Code Online (Sandbox Code Playgroud)

鉴于上述代码,以下内容无法编译

class Bad1 extends A {
  def f() = "unrelated string"
}
class Bad2 extends A {
  def f() = new C // this means that you can't just define a type parameter on
                  // A like A[T <: A] with f() defined as f: T
}
class Bad3 extends D // f() now doesn't return the correct type
Run Code Online (Sandbox Code Playgroud)

这种关系有名字吗?它是如何在Scala中注释/实现的?

编辑

您可以看到以下类型的作品:

scala> trait A {
     | def f: this.type 
     | }
defined trait A

scala> class C extends A {
     | def f = this 
     | }
defined class C

scala> class D extends A {
     | def f = new D
     | }
<console>:7: error: type mismatch;
 found   : D
 required: D.this.type
       def f = new D
               ^
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题?

编辑2

使用第二个系统,我可以做到这一点,这很好地符合D类的定义:

scala> trait A[T <: A[T]] { def f(): T }
defined trait A
// OR
scala> trait A[T <: A[T]] { self: T =>
     | def f(): T
     | }

scala> class C extends A[C] { def f() = new C }
defined class C

scala> class D extends C
defined class D

scala> (new D).f
res0: C = C@465fadce
Run Code Online (Sandbox Code Playgroud)

Raf*_*cki 14

我担心没有可能知道扩展类的扩展类是什么.

最接近你想要的东西类似于C++中众所周知的Curiously Recurring Template Pattern(CRTP).

trait A[T <: A[T]] {
  def f(): T;
}

class C extends A[C] {
  def f() = new C
}

class D extends A[D] {
  def f() = new D
}
Run Code Online (Sandbox Code Playgroud)


ten*_*shi 6

你可以做的一件事是返回类型this.type:

trait A {
  def f(): this.type
}

class C extends A {
  def f() = this
}

class D extends A {
  def f() = this
}

class Z extends D {
  override def f() = this
  def x = "x"
}

println((new Z).f().x)
Run Code Online (Sandbox Code Playgroud)

这对建筑商来说非常有用.

  • @aharon:是的,`this.type`是一种单身人士类型.你可以更多地了解它[这里](http://scalada.blogspot.com/2008/02/thistype-for-chaining-method-calls.html).所以不是所有可能的场景...... (2认同)

ten*_*shi 5

这是另一种可能的解决方案。它是 self 类型 + 类型参数的组合:

trait A[T <: A[T]] { self: T =>
  def f(): T
}

class Z extends A[Z] {
  override def f() = new Z
  def x = "x"
}

println((new Z).f().x)
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到有关此解决方案的更多信息:

scala self-type:值不是成员错误