2016-12-15 66 views
1

在下面的代码中,有一个DogSearcher,它有一个名为fetch的方法,期望一个Ball。我们也可以使用CatSearcher,它具有期望Bell的获取方法。我们的想法是,我们可以调用从PetSearcher继承的实例的提取并为其提供不同的参数。Scala - 调用上层实例的方法

任何想法我失踪?

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() 

回答

2

DogSearch的search方法不会覆盖PetSearcher的search方法,因为参数类型是不同的(what是PetSearcher一个Thing但DogSearcher一个Ball - 这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的在PET中,通过将类型参数F(事情,这种宠物搜索的亚型)到PetSearcher:

def fetch[S <: PetSearcher[F], F <: Thing](searcher: S, what: F): Unit = { 
+0

有没有办法说'DogSearcher扩展了PetSearcher [Ball]',然后让'search'方法知道应该接受'Ball'而不手动添加'Ball'到方法签名?如果你有20种方法,你不想在每个地方都复制'Ball' –

+1

我不这么认为,在scala中你必须给方法参数的类型。如果你想避免输入,一个好的IDE应该用IntelliJ和scala插件来帮助*覆盖*一个方法(例如,替换已经实现的特征)按下ctrl + o并选择方法 - 它将填充类型(包括在这种情况下类型是从参数派生的)。为了*实现*方法(即如果特征没有默认实现)按ctrl + i(这个快捷方式在实现特征时非常有用)。 –

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

+1

虽然这可行,但我实际上更喜欢@ JamesThorniley的回答,因为它限制了DogSearcher可以搜索的内容。还是谢谢你,这在其他情况下可能有用 – Sofia

+0

@Sofia当然,这一切都取决于你的用例。如果每个“PetSearcher”只应该能够查找单个项目类型,那么您将使用该类型对类进行参数化。 –

+0

@Sofia也作为旁白,'fetch [DogSearcher,Ball](searcher,ball)'可以写成'fetch(searcher,ball)',添加类型在这里是多余的。 –