指定超类参数时,Scala函数为什么允许子类参数

时间:2019-08-28 21:18:21

标签: scala covariance contravariance

<:似乎像我期望的那样工作,但是>:不能。

object TheCakeIsALie extends App {
  class Food
  class Junk extends Food
  class Cake extends Junk

  val food = new Food
  val junk = new Junk
  val cake = new Cake

  def subJunk[T <: Junk](food: T) = println(s"${food.getClass.getSimpleName} <: Junk")
  // subJunk(food)
  subJunk(junk)
  subJunk(cake)

  def superJunk[T >: Junk](food: T) = println(s"${food.getClass.getSimpleName} >: Junk")
  superJunk(food)
  superJunk(junk)
  superJunk(cake) // The cake is a lie!
}

subJunk(food)被注释掉是因为,正如预期的那样,它会产生编译时错误。 我希望superJunk(cake)也能做到这一点。

1 个答案:

答案 0 :(得分:2)

如果您想同时禁止subJunk(food)superJunk(cake),则最好使用隐式类型约束,而不要使用类型边界。

def subJunk[T](food: T)(implicit ev: T <:< Junk) = println(s"${food.getClass.getSimpleName} <: Junk")
// subJunk(food) // doesn't compile
subJunk(junk)
subJunk(cake)

def superJunk[T](food: T)(implicit ev: Junk <:< T) = println(s"${food.getClass.getSimpleName} >: Junk")
superJunk(food)
superJunk(junk)
// superJunk(cake) // doesn't compile

https://blog.bruchez.name/2015/11/generalized-type-constraints-in-scala.html