使用scala中使用的类型参数时感到困惑

时间:2018-02-23 00:20:43

标签: scala

我有以下简单的代码:

trait MyBox[T] {
  def capacity: Double
}

case class FruitBox[T](fruit: Int) extends MyBox[T] {
  override def capacity = 1.0
}


object FruitBox {
  def apply[T](fruit: Int): FruitBox[T] = new FruitBox[T](fruit)
}

以下代码也有效,我省略了类型参数T

case class FruitBox[T](fruit: Int) extends MyBox { //T is omitted for MyBox[T]
  override def capacity = 1.0
}


object FruitBox{
  def apply[T](fruit: Int): FruitBox[T] = new FruitBox(fruit) //T is omitted for new FruitBox
}

我会问为什么我可以省略类型参数?这背后的原因是什么?在我看来,在scala中,参数化类型必须具有类型参数才能成为具体类型。

1 个答案:

答案 0 :(得分:1)

为了防止可能的误解,这里不编译:

trait MyBox[T] {
  def capacity: Double
}

case class FruitBox[T](fruit: Int) extends MyBox {
  override def capacity = 1.0
}

你不能在这里省略[T],你会得到“错误:trait MyBox接受类型参数”。

问题的第二部分与MyBox或继承无关。由于完全相同的原因,这里的工作原理完全相同:

case class FruitBox[T](fruit: Int)

object FruitBox{
  def apply[T](fruit: Int): FruitBox[T] = new FruitBox(fruit)
}

可以从代码中省略type参数,但右侧的表达式new FruitBox(fruit)仍然是的正确类型 FruitBox[T]。这是因为返回类型FruitBox[T]可用于推断 = - 符号后面的表达式类型。编译器会自动添加[T],因此上面的定义只是

的简短形式
def apply[T](fruit: Int): FruitBox[T] = new FruitBox[T](fruit)

这类似于以下示例:

var foo: Set[String] = Set.empty

即使方法empty再次由类型参数化,也可以从声明的变量的类型推断出这个类型参数,以便代码有效地变为:

var foo: Set[String] = Set.empty[String]

类型推断会在其他几个案例中发挥作用,最突出的是:

  • 当表达式new FruitBox(i)作为参数出现在需要在该位置使用类型FruitBox[SomeType]的参数的方法时,编译器将自动推断出new FruitBox(i)实际上代表{{ 1}}。
  • 使用类型归属时:在new FruitBox[SomeType](i)中,编译器会自动将(new FruitBox(42) : FruitBox[String])添加到[String]调用中。