1

在下面的代码中,有一个 DogSearcher,它有一个名为 fetch 的方法,它需要一个 Ball。我们也可以有一个 CatSearcher,它带有一个期待 Bell 的 fetch 方法。这个想法是我们可以在继承自 PetSearcher 的实例上调用 fetch 并为其提供不同的参数。

知道我错过了什么吗?

trait PetSearcher {
  def search(what: Thing): Unit = {
    println("default searching")
  }
}

class DogSearcher extends PetSearcher {
  def search(what: Ball): Unit = {
    println("dog searching")
  }
}
trait Thing {
  val name: String
}
case class Ball(name: String) extends Thing

class Pet {
  def fetch[S <: PetSearcher, F <: Thing](searcher: S, what: F): Unit = {
    println(what)
    searcher.search(what)
  }
}

class Dog extends Pet {
  val searcher = new DogSearcher()
  val ball = new Ball("red")
  def go(): Unit = {
    fetch[DogSearcher, Ball](searcher, ball)
  }
}

//should use DogSearcher but calls fetch on Search, not on DogSearcher. 
// So prints default searching, not dog searching..
new Dog().go() 
4

2 回答 2

2

DogSearch的search方法不会覆盖searchPetSearcher 的方法,因为参数类型不同(对于 PetSearcherwhat是一个Thing,但Ball对于 DogSearcher 是一个 - 事实上BallextendsThing不足以使函数调用相同)。

PetSearcher一个类型参数来定义 的类型what,然后DogSearcher可以覆盖它(注意override关键字变得必要):

trait PetSearcher[T] {
  def search(what: T): Unit = {
    println("default searching")
  }
}

class DogSearcher extends PetSearcher[Ball] {
  override def search(what: Ball): Unit = {
    println("dog searching")
  }
}

为了让它编译,你还需要更新 PetSearcher 在 Pet 中的使用,通过将类型参数 F(这个 Pet 搜索的 Thing 的子类型)添加到 PetSearcher:

def fetch[S <: PetSearcher[F], F <: Thing](searcher: S, what: F): Unit = {
于 2016-12-15T16:07:08.827 回答
2

作为@JamesThorniley's answer的替代方案,您可以定义search接受任何扩展的内容Thing

trait PetSearcher {
    def search[T <: Thing](what: T): Unit = {
        println("default searching")
    }
}

class  DogSearcher extends PetSearcher {
    override def search[T <: Thing](what: T): Unit = {
        println("dog searching")
    }
}

这会dog searching根据需要输出。

于 2016-12-15T16:11:43.000 回答