Reputation: 16723
In the following example, I could compare two String
s using view bound
but not upper bound
even though on REPL, the <
method works for String
. Is it because String is not a subclass of Ordered[T] but there is an implicit conversion from String to Ordered[String]?
//view bound example. For String, It seems to work because I suppose there is an implicit conversion from String to Ordered[String]
scala> class Person[T <% Ordered[T]](val fn:T, val ln:T){
| def greater = if(fn > ln) fn else ln
| }
defined class Person
scala> val p1 = new Person("manu", "chadha")
p1: Person[String] = Person@f95d64d
scala> p1.greater
res0: String = manu
scala> val p2 = new Person("anita", "chadha")
p2: Person[String] = Person@30cafd13
scala> p2.greater
res1: String = chadha
//upper bound example. It doesn't work for String. Is it because String is not a subclass of Ordered[T] but there is an implicit converstion from String to Ordered[Strig]
scala> class Person2[T <: Ordered[T]](val fn:T, val ln:T){
| def greater = if(fn > ln) fn else ln
| }
defined class Person2
scala> val p3 = new Person2("manu", "chadha")
<console>:12: error: inferred type arguments [String] do not conform to class Person2's type parameter bounds [T <: Ordered[T]]
val p3 = new Person2("manu", "chadha")
^
<console>:12: error: type mismatch;
found : String("manu")
required: T
val p3 = new Person2("manu", "chadha")
^
<console>:12: error: type mismatch;
found : String("chadha")
required: T
val p3 = new Person2("manu", "chadha")
^
I suppose view bounds are deprecated. So how does the following example work in REPL?
scala> "manu" > "Manu"
res2: Boolean = true
Upvotes: 0
Views: 63
Reputation: 7353
Exactly. "a" < "b"
is desugared as
scala.Predef.augmentString("a") < "b"
Where augmentString("a")
is a class StringOps, which is also Ordered[String]
, where <
comes from.
View bounds syntax is deprecated, but the implicit conversions and parameters are not. So the way your code is written in the modern Scala is just using an implicit parameter which is an implicit conversion as well:
class Person[T](val fn:T, val ln:T)(implicit view: T => Ordered[T]){
def greater = if(fn > ln) fn else ln
}
Although it's generally considered best practice to use typeclasses. Here, we have scala.math.Ordering
in standard library:
import Ordering.Implicits._ // brings operators like "<" into the scope
class Person[T](val fn: T, val ln: T)(implicit val order: Ordering[T]) {
def greater = if (fn > ln) fn else ln
}
Which have the syntactic form of context bounds that is not deprecated:
import Ordering.Implicits._ // brings operators like "<" into the scope
class Person[T: Ordering](val fn: T, val ln: T) {
def greater = if (fn > ln) fn else ln
}
This is the equivalent of Java's Comparable
vs Comparator
, except you don't have to pass Comparator
instances manually
assert { new Person("manu", "chadha").greater == "manu" }
Upvotes: 2