特征中的覆盖函数

Fre*_*son 5 scala

假设我有以下特征

trait Foo[T] {
  def overrideMe(other:Foo[T]) : Int
}
Run Code Online (Sandbox Code Playgroud)

我希望能够做到

class Bar extends Foo[Int] {
   override  def overrideMe(other:Bar) : Int = other.BarFn
}
Run Code Online (Sandbox Code Playgroud)

但它没有编译.原因是我希望overrideMe能够使用子类型的功能.我可以做点什么

class Bar extends Foo[Int] {
   override  def overrideMe(other:Foo[Int]) : Int = {
      other.asInstanceOf[Bar].BarFn
}
Run Code Online (Sandbox Code Playgroud)

但这看起来不太好.

是否有可能在特征中说可以用子类型覆盖虚函数?

编辑 @agilesteel这几乎可以工作,但如果我在另一个只依赖于特性Foo的类中有一个函数,我会遇到麻烦

class Test[T] {
    def callOverrideMe(a : Foo[T], b : Foo[T] ) : Int = a.overrideMe(b)
}
Run Code Online (Sandbox Code Playgroud)

我得到一个编译错误:类型不匹配; 发现b.type(底层类型为foo.Foo [T])需要a.SubType

agi*_*eel 7

trait Foo[T] {
  type TheSubType <: Foo[T]
  def overrideMe(other: TheSubType) : Int
}

class Bar extends Foo[Int] {
   type TheSubType = Bar
   override def overrideMe(other: Bar) : Int = other.barFn
   def barFn = 10
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*nov 6

class Test[T] {
    def callOverrideMe(a : Foo[T], b : Foo[T] ) : Int = a.overrideMe(b)
}
Run Code Online (Sandbox Code Playgroud)

当然,你无法使用这个签名.考虑一下

class Baz extends Foo[Int] {...}

new Test[Int].callOverrideMe(new Bar, new Baz)
Run Code Online (Sandbox Code Playgroud)

这应该是相同的new Bar.overrideMe(new Baz),但你不希望它编译!

您可以使用奇怪的重复模板模式:

trait Foo[T, Sub <: Foo[T, Sub]] {
  def overrideMe(other:Sub) : Int
}

class Bar extends Foo[Int, Bar] {
   override def overrideMe(other:Bar) : Int = other.BarFn
}

class Test[T] {
    def callOverrideMe[Sub <: Foo[T, Sub]](a : Sub, b : Sub) : Int = a.overrideMe(b)
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是依赖于特征的算法,然后在子类型中实现一些功能.还有其他好的设计模式吗?

查看Scalaz类型类.例如https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Equal.scala