Scala 上限

Bus*_*Bee 2 scala upperbound type-bounds

在典型的 Scala 上限示例中

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 Lion extends Animal {
  override def name: String = "Lion"
}
Run Code Online (Sandbox Code Playgroud)

这有什么区别

class PetContainer[P <: Pet](p: P) {
      def pet: P = p
    }

val dogContainer = new PetContainer[Dog](new Dog)
val catContainer = new PetContainer[Cat](new Cat)
Run Code Online (Sandbox Code Playgroud)

和这个?

class PetContainer1(p: Pet) {
      def pet: Pet = p
    }

val dogContainer1 = new PetContainer1(new Dog)
val catContainer1 = new PetContainer1(new Cat)
Run Code Online (Sandbox Code Playgroud)

使用上限类型与直接使用抽象类/特征相比有什么优点?

mic*_*JlS 6

使用上限,您可以拥有特定子类型的集合 - 因此仅限于猫或狗,您可以从 中获取特定子类型def pet。对于 来说,情况并非如此PetContainer1

丢失更准确的类型信息示例:

val doggo: Dog = new Dog
val dogContainer1 = new PetContainer1(doggo)
// the following won't compile
// val getDoggoBack: Dog = dogContainer1.pet  

val dogContainer2 = new PetContainer[Dog](doggo)
// that works
val getDoggoBack: Dog = dogContainer2.pet  
Run Code Online (Sandbox Code Playgroud)

你不能把猫放入狗容器中:

// this will not compile
new PetContainer[Dog](new Cat)
Run Code Online (Sandbox Code Playgroud)

如果您要处理多个元素的集合,它会变得更加重要。

  • 从您的示例来看,假设您想从宠物容器(我们称之为“pc”)中取出“Dog”。如果它是 `PetContainer[Dog]`:`val dog: Dog = pc.pet`。如果它是一个“PetContainer1”,我们只知道它是一个“Pet”,所以你需要类似的东西(通常会表示为模式匹配,但 if/isInstanceOf/asInstanceOf 在 SO 注释中效果更好): `val pet: Pet = pc.pet; val 狗: 狗 = if (pet.isInstanceOf[Dog]) pet.asInstanceOf[Dog] else ???` (2认同)