【问题标题】:define method to return type of class extending it定义方法以返回扩展它的类的类型
【发布时间】:2011-07-16 22:43:10
【问题描述】:

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

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
}

鉴于上面的代码,以下将无法编译

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

这种关系有名称吗?它是如何在 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
               ^

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

编辑 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

【问题讨论】:

    标签: scala types


    【解决方案1】:

    恐怕无法从扩展类中知道扩展类是什么。

    与您想要的最接近的是类似于 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
    }
    

    【讨论】:

    • 这样效果更好,但是有什么办法可以解决第二次编辑中显示的问题吗?
    【解决方案2】:

    您可以做的一件事是返回类型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)
    

    这对建筑商很有用。

    【讨论】:

    • 这并不适用于所有情况,尽管总比没有好。有关详细信息,请参阅帖子中的编辑。
    • @aharon:是的,this.type 是一种单身类型。你可以更多地了解它here。所以它并不适用于所有可能的情况......
    【解决方案3】:

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

    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)
    

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

    scala self-type: value is not a member error

    【讨论】:

    • 这样效果更好,但是有什么办法可以解决第二次编辑中显示的问题吗?
    猜你喜欢
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2023-04-04
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    相关资源
    最近更新 更多