Reputation: 6342
I have following simple code:
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)
}
The following code is also valid that I omit the type parameter 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
}
I would ask why I could omit the type parameter? What is the reason behind this?It looks to me that in scala,parameterized type must have type parameter to be a concrete type.
Upvotes: 0
Views: 102
Reputation: 44957
Just to prevent a possible misunderstanding, this here does not compile:
trait MyBox[T] {
def capacity: Double
}
case class FruitBox[T](fruit: Int) extends MyBox {
override def capacity = 1.0
}
You can't omit [T]
here, you would get "error: trait MyBox takes type parameters".
The second part of your question has nothing to do with MyBox
or inheritance at all. This here would work in exactly the same way, for exactly the same reasons:
case class FruitBox[T](fruit: Int)
object FruitBox{
def apply[T](fruit: Int): FruitBox[T] = new FruitBox(fruit)
}
The type parameter can be omitted from the code, but the expression new FruitBox(fruit)
on the right hand side is still of the right type FruitBox[T]
. This is because the return type FruitBox[T]
can be used to infer the type of the expression that comes after the =
-sign. The compiler adds the [T]
automatically, so that the above definition is just a short form of
def apply[T](fruit: Int): FruitBox[T] = new FruitBox[T](fruit)
This is similar to the following example:
var foo: Set[String] = Set.empty
Even though the method empty
is again parameterized by a type, this type parameter can be inferred from the type of the declared variable, so that the code effectively becomes:
var foo: Set[String] = Set.empty[String]
Type inference would kick in in several other cases, most prominently:
new FruitBox(i)
appears as an argument to a method that requires an argument of type FruitBox[SomeType]
at that position, then the compiler will automatically infer that new FruitBox(i)
actually stands for new FruitBox[SomeType](i)
.(new FruitBox(42) : FruitBox[String])
, the compiler will automatically add [String]
to the new
invokation.Upvotes: 1