object Main extends App {
def foo[K >: Baz](a: K): Unit = ???
foo(new Foo)
foo(new Baz)
foo(new Bax)
foo("fi")
}
class Foo
class Baz extends Foo
class Bax extends Baz
My understanding of K >: Baz - K can be of type Baz or any super type of Baz.
But the code seems to compile with any type. I am pretty sure I have misunderstood something here?
As @tarsa said, this works because scala is free to pick any supertype of Baz of which there is always at least one, namely Any (actually AnyRef/Object in this case).
This shows it more clearly:
@ def foo[K >: Baz](a: K): Unit = println(a)
defined function foo
@ foo[AnyRef]("fi")
fi
@ foo[String]("fi")
cmd17.sc:1: type arguments [String] do not conform to method foo's type parameter bounds [K >: ammonite.$sess.cmd2.Baz]
val res17 = foo[String]("fi")
^
Compilation Failed
Where lower type bounds are often used is when the function automatically widens the return type based on the type parameter to the function.
One use case you have probably seen is for scala.Option#getOrElse which is defined as:
def getOrElse[B >: A](default: => B): B
Which you can see will infer B to be the lowest common supertype of A and the parameter default:
I’ll jump in with an opinion: having picked up Ammonite a couple of months ago, I’m a fan. The power of the REPL aside, being able to do shell scripting in Scala is a revelation for me – it is so much easier than traditional scripting languages for me. I find myself actually looking forward to writing scripts, which is new and different.
(This is all from the viewpoint of already knowing Scala pretty well, mind. But if you do, it’s well worth checking out.)
I have only just started using it in the past few weeks and I really like it. Even the simple things like being able to import dependencies and the ability to edit your code if you make a mistake or want to modify it are really nice.