我试图理解scala中的“下界”。请找到以下示例
class Animal
class Dog extends Animal
class Puppy extends Dog
class Human extends Animal
class Plant
class AnimalDisplay{
def displayUptoDog [T >: Dog](t: T){
println(t)
}
def displayUptoAnimal [T >: Animal](t: T){
println(">>"+t.getClass())
}
}
object ScalaLowerBoundsTest {
def main(args: Array[String]) {
val animal = new Animal
val dog = new Dog
val puppy = new Puppy
val human=new Human
val plant = new Plant
val animalDisplay = new AnimalDisplay
println("Upto Animal")
animalDisplay.displayUptoAnimal(animal)
animalDisplay.displayUptoAnimal(dog)
animalDisplay.displayUptoAnimal(puppy)
animalDisplay.displayUptoAnimal(human)
animalDisplay.displayUptoAnimal(plant)
println("Upto Dog")
animalDisplay.displayUptoDog(animal)
animalDisplay.displayUptoDog(dog)
animalDisplay.displayUptoDog(puppy)
// prints: com.typeSystem.typeBound.lowerBound.Puppy@1b6d3586
animalDisplay.displayUptoDog(human)
//print:com.typeSystem.typeBound.lowerBound.Human@4554617c
animalDisplay.displayUptoDog(plant)
//prints:com.typeSystem.typeBound.lowerBound.Plant@74a14482
}
}
我的问题是
因为Puppy不是狗,也不是超级狗
为什么允许animalDisplay.displayUptoDog(puppy)
?一些真实的
usecase将帮助我更好地理解
如果允许(animalDisplay.displayUptoDog(puppy))
,那么它
应该
打印com.typeSystem.typeBound.lowerBound.Dog@xxxxx
而不是
com.typeSystem.typeBound.lowerBound.Puppy@1b6d3586
让我知道我是否遗漏了一些东西
答案 0 :(得分:0)
animalDisplay.displayUptoDog(puppy)
,因为您可以将Puppy
投射到Dog
,如下所示:
animalDisplay.displayUptoDog(puppy: Dog)
现在您可能会问,如果您可以简单地将对象转发到T
以使其适合,那么在方法签名中使用T
的下限有什么意义呢?要回答这个问题,我认为最好看一个例子,其中下限确实有用甚至是必要的。
下限的一个非常常见的用例是,当您希望确保某些方法返回与某些其他类型相同的类型值时,例如在Option[A]
中有一个方法:
def getOrElse[B >: A](default: ⇒ B): B
如果我们想要A
和B
常见的类型,唯一合理的选择是当A
是B
的子类型时。在相反的情况下(B <: A
),如果该选项是A
,则您无法返回Some[A]
,因为A
不是B
的子类型。
以下是将它应用于Dog
类层次结构时的工作原理示例:
val d1 = Some(dog).getOrElse(puppy)
d1: Dog = $sess.cmd1$Dog@55e02661
val d2 = (None: Option[Dog]).getOrElse(puppy)
d2: Dog = $sess.cmd2$Puppy@420068a
val d3 = Some(puppy).getOrElse(dog)
d3: Dog = $sess.cmd2$Puppy@420068a
val d4 = (None: Option[Puppy]).getOrElse(dog)
d4: Dog = $sess.cmd1$Dog@55e02661
正如您在所有情况下所看到的,它的行为符合预期。在getOrElse
和A
为B
或Dog
时调用Puppy
始终会返回两个共同的类型,即Dog
。< / p>