This has been asked a lot of times, and I think that the confusion can easily go away if you see the analogy between type parameters and constructor parameters, thinking about them just as different kinds of constructor parameters: type-level and value-level.
Disclaimer Of course, this is only an analogy and it will break at a lot of different levels and there are a lot of corner cases as with anything Scala; but my point here is that it can be useful
At the type level, you can think of <:
as a the equivalent of :
at the value level:
class TypeParamsVsVals {
type X
type X1 <: X
class Buh[T <: X]
class Oh[T1 <: X1] extends Buh[T1]
// wait for Scala 3
// class Oh[T1 <: X1] extends Buh[T = T1]
type x
type x1 <: x
class buh(val t: x)
class oh(val t1: x1) extends buh(t = t1)
}
What I think is the main source of confusion is that at the type level there's no kind distinction between the two sides of <:
, and to make things worse you can write T
without any (no pun intended) bound, while you cannot do the same at the value level:
class NoBounds[T]
// same as
class AltNoBounds[T <: Any]
// you cannot write
// class noBounds(val t)
class noBounds(val t: Any)
case class Hey() extends Worker[Asset] { def hey() = "You!" }
works just fine. As to why, no idea, although I haven't really put much thought to it, honestly :) – Patryk Ćwiekcase class Hey[Asset] extends Worker[Asset]
andcase class Hey[T] extends Worker[T]
means the same.Asset
here is just a new name for type parameter of classHey
. See stackoverflow.com/a/19137992/406435 – senia