与scala中使用的类型参数的用法混淆

与scala中使用的类型参数的用法混淆,scala,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

我有以下简单的代码:

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中,参数化类型必须具有类型参数才能成为具体类型。

为了避免可能的误解,这里不编译:

trait MyBox[T] {
  def capacity: Double
}

case class FruitBox[T](fruit: Int) extends MyBox {
  override def capacity = 1.0
}
您不能在这里省略
[t]
,您将得到“error:trait MyBox接受类型参数”


问题的第二部分与
MyBox
或继承无关。这将以完全相同的方式工作,原因完全相同:

case class FruitBox[T](fruit: Int)

object FruitBox{
  def apply[T](fruit: Int): FruitBox[T] = new FruitBox(fruit)
}
类型参数可以从代码中省略,但右侧的表达式
new-FruitBox(fruit)
仍然是正确的类型
FruitBox[T]
。这是因为返回类型
水果盒[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)
    实际上代表
    new-FruitBox[SomeType](i)
  • 当您在
    中使用类型归属时(新的水果盒(42):水果盒[String])
    ,编译器将自动将
    [String]
    添加到
    新的
    调用中