Scala:如何引用超类中扩展类的类型?

jhe*_*dus 3 types scala

有没有办法T在Parent中定义一个类型,T总是成为扩展类的实际类型(在这种情况下Child)?

Parent,我想执行/宣称T要始终延伸型,仿佛我会写type T="type_of_the_extending_class"在每个实际的继承类,而无需实际写下线type T=Child1Child1

所以Child1的方法只接受Child1对象作为参数,Child2的方法只接受Child2对象.有没有更简单的方法来强制执行此操作?有没有办法没有type T=ChildX在每个ChildX班级写作?有没有这种样板的方法?

我一直在寻找Scala书籍的解决方案,但没有找到任何解决方案.

abstract class Parent{
  type T<:Parent
  def method(t:T) 
}

class Child1 extends Parent{
  type T=Child1
  override def method(t:T)=t.child1method
  def child1method=println("child1's method")
}

class Child2 extends Parent{
  type T=Child2
  override def method(t:T)=t.child2method
  def child2method=println("child2's method")
}
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 7

这个问题的标准解决方案是F -bounded多态(它不是Scala特定的 - 你会发现它在Java中使用,等等):

trait Parent[T <: Parent[T]] {
  def method(t: T)
}

class Child1 extends Parent[Child1] {
  def method(t: Child1) = println("child1's method")
}

class Child2 extends Parent[Child2] {
  def method(t: Child2) = println("child1's method")
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,有一些关于Scala社区中F -bounded多态性的抱怨- 例如Kris Nuttycombe说它"难以正确并导致在代码库中打字混乱",而且我个人发现我使用它更少经过几年的Scala写作后不太常见.但是,当您的程序体系结构导致您需要这种继承时,它正是该工作的正确工具.

这个问题this.type(在评论中提到的)是,它不会让你做的大部分事情你会合理要做,过于具体:

scala> abstract class Parent {
     |   def method(t: this.type)
     | }
defined class Parent


scala> class Child1 extends Parent {
     |   def method(t: this.type) = println("child1's method")
     | }
defined class Child1

scala> val a = new Child1
a: Child1 = Child1@19517e9a

scala> val b = new Child1
b: Child1 = Child1@5737e545

scala> a.method(b)
<console>:12: error: type mismatch;
 found   : b.type (with underlying type Child1)
 required: a.type
              a.method(b)
                       ^
Run Code Online (Sandbox Code Playgroud)

我们唯一可以传递的论点a.method就是a它自己.