In a typical Scala upperbound example
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"
}
What is the difference between this
class PetContainer[P <: Pet](p: P) {
def pet: P = p
}
val dogContainer = new PetContainer[Dog](new Dog)
val catContainer = new PetContainer[Cat](new Cat)
and this?
class PetContainer1(p: Pet) {
def pet: Pet = p
}
val dogContainer1 = new PetContainer1(new Dog)
val catContainer1 = new PetContainer1(new Cat)
What is the advantage of using an upper type bound vs using the abstract class/trait directly?