下界 Scala

huangapple go评论76阅读模式
英文:

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 &lt;: Animal](animal: A)

Lower bound

  class CageLB[A &gt;: 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 = &#39;B&#39;}
class Mid extends Base {val mid  = &#39;M&#39;}
class End extends Mid  {val end  = &#39;E&#39;}

Now let's start with the more common upper bounding.

def f[T &lt;: Mid](t:T):Int = {
  val x = t.base
  val y = t.mid
//val z = t.end  &lt;--won&#39;t compile
  42
}
//f(new Base)  &lt;--doesn&#39;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 &gt;: Mid](t:T):Int = {
//val x = t.base &lt;--won&#39;t compile
//val y = t.mid  &lt;--won&#39;t compile
//val z = t.end  &lt;--won&#39;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.

huangapple
  • 本文由 发表于 2020年10月24日 04:19:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/64506786.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定