首页 > 解决方案 > Scala中上界优于子类型的优势

问题描述

我知道这个问题在这里之前已经被问过。但是那里的答案并不能满足我的怀疑。
有人告诉我它们可以防止混淆类类型,下面的代码表明它们根本没有混淆。
所以,应该没关系吧?

课程:

package Practice

abstract class Animal {
  def name: String
}

abstract class Pet extends Animal {}

class Cat extends Pet {
  override def name: String = "Cat"
}

class Dog extends Pet {
  override def name: String = "Dog"
}

这是真正的困惑:

//Class with Upper Bound
class PetContainer[P <: Pet](p: P) {
  def pet: P = p
}

//Class with Subtyping(Or Upcasting, I think they're the same)
class SimplePetContainer(p: Pet){
  def pet: Pet = p
}

驱动程序代码:

val CatContainer: PetContainer[Cat] = new PetContainer[Cat](new Cat)
val DogContainer: SimplePetContainer = new SimplePetContainer(new Dog
println(CatContainer.pet.getClass)
println(DogContainer.pet.getClass)

输出:

class Practice.Cat
class Practice.Dog
//Practice was the package

就像我之前提到的,这些类被保留了。
所以我的问题是,Upper Bound 对 Subtyping 有什么优势?

标签: scala

解决方案


使用您的CatContainer,您知道这CatContainer.petCat在编译时。这意味着编译器也知道这一点。所以你可以说

 CatContainer.pet.meow()

因为SimplePetContainer你不再有关于pet内部的静态类型信息。

就像我之前提到的,这些类被保留了。

在运行时,pet当然仍然知道它的类型(嗯,几乎,它知道它的类,在你的情况下就足够了,任何额外的类型信息,例如该类的泛型类型都已被删除)。但是该变量DogContainer.pet缺少关于Pet它包含何种类型的信息。

有人告诉我,它们可以防止混淆班级类型

编译器不会阻止你写作

val DogContainer = new SimplePetContainer(new Cat())

但它会拒绝这个

val DogContainer = new PetContainer[Dog](new Cat())

推荐阅读