英文:
Lower Bound Scala
问题
类 Animal
类 Cat 扩展自 Animal
类 Dog 扩展自 Animal
上界(Upper bound)
类 CageUP[A <: Animal](animal: A)
下界(Lower bound)
类 CageLB[A >: Animal](animal: A)
根据上界定义,它可以接受的 A 必须是 Animal 相同或 Animal 的子类型。
val cageup = new CageUP(new Dog)
根据下界定义,它可以接受的 A 必须是 Animal 相同或 Animal 的超类型。
val cagelb = new CageLB(new Dog)
为什么下界可以接受并编译,即使传递了 Dog 实例,它并不是 Animal 的超类型。
英文:
class Animal
class Cat extends Animal
class Dog extends Animal
Upper bound
class CageUP[A <: Animal](animal: A)
Lower bound
class CageLB[A >: Animal](animal: A)
As per the upper bound definition, it can accept A must be either same as Animal or Sub-Type of Animal.
val cageup = new CageUP(new Dog)
As per the lower bound definition, it can accept A must be either same as Animal or Super-Type of Animal.
val cagelb = new CageLB(new Dog)
Why lower bound is accepting and compiling even dog instance is passed, which is not a supertype of Animal.
答案1
得分: 2
Type bounds effect methods at both the call site and the definition site, sometimes in surprising ways.
Let's set up a type hierarchy.
class Base {val base = 'B'}
class Mid extends Base {val mid = 'M'}
class End extends Mid {val end = 'E'}
Now let's start with the more common upper bounding.
def f[T <: Mid](t:T):Int = {
val x = t.base
val y = t.mid
//val z = t.end <--won't compile
42
}
//f(new Base) <--doesn't conform to bounds
f(new Mid) //OK
f(new End) //OK, promoted to Mid in the f() code
As expected, there is no t.end
because that's not a part of type Mid
, and you can't invoke it with type Base
because that won't have the mid
member expected in every type Mid
.
Now let's flip it to lower bounding.
def f[T >: Mid](t:T):Int = {
//val x = t.base <--won't compile
//val y = t.mid <--won't compile
//val z = t.end <--won't compile
42
}
f(new Base) //OK
f(new Mid) //OK
f(new End) //OK
f(List(9)) //OK!!
As you can see, a received parameter with no upper bound isn't terribly useful because the compiler sees that it might be type Mid
, but it might be type Any
, and since anything and everything can be promoted to type Any
, then anything is permitted at the call site, but almost nothing is known about it at the method definition site.
英文:
Type bounds effect methods at both the call site and the definition site, sometimes in surprising ways.
Let's set up a type hierarchy.
class Base {val base = 'B'}
class Mid extends Base {val mid = 'M'}
class End extends Mid {val end = 'E'}
Now let's start with the more common upper bounding.
def f[T <: Mid](t:T):Int = {
val x = t.base
val y = t.mid
//val z = t.end <--won't compile
42
}
//f(new Base) <--doesn't conform to bounds
f(new Mid) //OK
f(new End) //OK, promoted to Mid in the f() code
As expected, there is no t.end
because that's not a part of type Mid
, and you can't invoke it with type Base
because that won't have the mid
member expected in every type Mid
.
Now let's flip it to lower bounding.
def f[T >: Mid](t:T):Int = {
//val x = t.base <--won't compile
//val y = t.mid <--won't compile
//val z = t.end <--won't compile
42
}
f(new Base) //OK
f(new Mid) //OK
f(new End) //OK
f(List(9)) //OK!!
As you can see, a received parameter with no upper bound isn't terribly useful because the compiler sees that it might be type Mid
, but it might be type Any
, and since anything and everything can be promoted to type Any
then anything is permitted at the call site but almost nothing is known about it at the method definition site.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论