Part one is an useful read as it gives a good introduction to types and prepares the field.
All mechanisms presented here offer insights on how to apply constraints to the type parameters.
Looking back to part three
of the variance series of articles, the two methods,
appEventFired are certainly in need of some improvements.
Assuming that both of these methods handle
in the same way, the duplication can be removed considering that the two events
are sub-types of
An useful heuristic for understanding the
<: symbol is:
The mechanism that allows this kind of constraint setting, made available by
Scala’s type system is called
This kind of bound is called an
upper bound and the syntax is
T <: UpperBoundType.
Scala also supports
lower bounds, and, unsurprisingly, the syntax is
T >: LowerBoundType.
Consider the following contrived example, a method that receives an event and an event source and filters out the events that are errors:
A useful heuristic for understanding the
>: symbol is:
In this scenario, the
e param is constrained to be only of type
SystemEvent but not of type
src param is constrained to be only of type
Source[ErrorEvent]. This is a direct
consequence of covariance.
The following call compiles just fine:
As a reminder, the type of
Obviously, the method compiles even if you pass it a
A context bound has the syntax
T : M.
An useful heuristic for understanding the syntax is:
Now there’s a good time to go back to this article.
is presented as ‘alternative syntax’ since I did not want to introduce another concept (bounds) while dealing with type classes.
Applied to this example, the heuristic is:
The following lines create a
Document and pass it to the
which will take care of the conversion.
The heuristic in this case:
The Manifest Context Bound
This presentation would not be complete without mentioning the manifest context bound.
T : Manifest.
Manifests were added to Scala especially for arrays and were generalized to be
useful in other situations where type information must be available at runtime.
In other words,
Manifests are a way to achieve
reification on the JVM.
Array is a parameterized class. For example, an array of integers has
Array[Int]. So code can be written for generic
Array[T] types, but
because on the JVM there are different types of arrays for every primitive type
and for objects (for example
String), a way to retain
this specialized type information was required so that generic array
implementations would know what underlying type is required.
To instantiate a generic
Manifest[T] object is needed.
Using the aforementioned heuristic(s), we have:
Manifest[T] is generated by the compiler, when needed, with all the
known information for that type at that time.