类型的表达式不符合预期类型B.

时间:2017-07-29 09:36:47

标签: scala

我有以下代码来理解协变和下界,我故意让代码编译错误。

getOrElse有效,与选项[+ T]的getOrElse方法类似。

我会问为什么getOrElse2getOrElse3不能更好地理解协变和下限。

编译错误在代码中粘贴为注释:

class  MyOption[+A](val x: A) {
  def get():A = x

  //similar to Option.getOrElse,which works
  def getOrElse[B>:A ](default: => B): B = {
    if (x != null) x else  default
  }

  //Compiling Error: Expression of type A doesn't conform to Expected type B
  def getOrElse2[B, A<:B ](default: => B): B = {
    if (x != null) x else  default
  }

  //Covariant type A occurs in controvariant position in type A of value B
  def getOrElse3[B <: A](default:=>B): A = {
    if (x != null) x else  default
  }
}

2 个答案:

答案 0 :(得分:1)

1. getOrElse3[B <: A]:表示类型为B 控制 AB子类型/下限 A协变类型 A不允许这样做,因为协变类型仅启用超类型绑定对于A类型。而且这等于:

//Error:covariant type A occurs in contravariant position in type A of value default
def getOrElse3(default: A): A = {
  if (x != null) x else default
}

为什么选项类型协方差?这是用于将A绑定到超类型A ,如Some(1)可以由接受参数的方法Option[AnyVal]使用。

2. def getOrElse2[B, A<:B ]A<:B这意味着定义子类型A的新类型B(不是类级别类型A)。并且由于您将类通用类型x的{​​{1}}返回到类型A,编译器应该抛出类型不匹配错误。

答案 1 :(得分:1)

通过为方法[A <: B]指定getOrElse2,您需要定义与A所属的原始类型A无关的新本地类型x如@ chengpohi的回答中所述。

对于方法getOrElse3[B <: A]违反trait Function1的定义,要求其参数为逆变:

trait Function1[-T1, +R] extends AnyRef {
  abstract def apply(v1: T1): R
  // ...
}

对于协变量[+ A],对于S的子类型A,MyOption [S](x:S)的实例可以替换MyOption [A]的实例(x:A) );但由于Function1参数的逆变要求,getOrElse3 [S]无法替换getOrElse3 [A]。出于同样的原因,以下方法也会使编译器失败:

// Compiling Error: covariant type A occurs in contravariant position in type A of value default
def printDefault(default: A): Unit = {
  println(default)
}

要保留您的协变[+ A],将A设置为与您的第一个getOrElse方法相同的下限,可以避免冲突Function1参数的逆转。