Scala - 在上限实例上调用方法
Scala - call method on upper bounded instance
在下面的代码中,有一个 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()
DogSearch 的 search
方法不会覆盖 PetSearcher 的 search
方法,因为参数类型不同(what
是 PetSearcher 的 Thing
但 Ball
对于 DogSearcher - Ball
扩展 Thing
的事实不足以使函数调用相同。
让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 的使用,方法是将类型参数 F(此 Pet 搜索的 Thing 的子类型)添加到 PetSearcher:
def fetch[S <: PetSearcher[F], F <: Thing](searcher: S, what: F): Unit = {
作为 的替代方法,您可以定义 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
。
在下面的代码中,有一个 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()
DogSearch 的 search
方法不会覆盖 PetSearcher 的 search
方法,因为参数类型不同(what
是 PetSearcher 的 Thing
但 Ball
对于 DogSearcher - Ball
扩展 Thing
的事实不足以使函数调用相同。
让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 的使用,方法是将类型参数 F(此 Pet 搜索的 Thing 的子类型)添加到 PetSearcher:
def fetch[S <: PetSearcher[F], F <: Thing](searcher: S, what: F): Unit = {
作为 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
。