I am trying to understand the type parameters in Scala. Let's look the following general example:
def func1[T](a : T) : T = a
I understand that func1 takes 1 parameter of any type, and returns that parameter of the very same type. What i don't understand is why:
def func1[T]
Why [T] right after function1?? We could simply write it without [T] after func1, like:
def func1(a : T) : T = a
1) What does that [T] means after func1 and why we put it there?
2) Why we do the same with classes?
class MyClass[T]{...}
I mean MyClass instantiations are of type MyClass. What does [T] means there?
You don't say i have a boolean Class of type MyClass, you say i have an object of type MyClass right?
Thanks in advance.
- What does [T] mean after
func1
, and why do we put it there?
The [T]
in func[T]
defines a type parameter T
. Your function can be called like func[String]("Hello")
, in which String
is replaced with T
. You can also call it like func("Hello")
because the Scala compiler is smart enough to infer that T
must be String
.
So why do we have to write func[T]
when we define it? We need the distinction between arguments of a type given by a type parameter, and arguments given by an actual type. If you write it this: def func1(a : T) : T = a
, then T
has to be an actual type. For example:
class T
def func1(a : T) : T = a // <-- This compiles now
- Why do we do the same with classes?
You often want to contain an object of some type inside a class. If you define the type parameter at the class level, the type will remain the same throughout your class. Consider this example:
class Container[T](val t: T) {
def isValueEqual(obj: T): Boolean = t.equals(obj)
}
Here, the T
in obj: T
is the same type as the T
defined in Container[T]
. Now consider this example:
class Container[T](val t: T) {
def isValueEqual[T](obj: T): Boolean = t.equals(obj)
}
Notice that I defined a new type parameter at the method level as well (isValueEqual[T]
). In this case, the T
defined in the method will shadow the T
defined on the class level. This means that they might not be the same type! You could call it like this:
val c = new Container("Hello")
println(c.isValueEqual(5)) // 5 is not of type String!