In Scala. I have two objects of type Any. If it's possible, I'd like to cast the objects to the correct Ordered trait, and then compare them with the < method. Otherwise, I want to throw an exception. Should be simple, but I'm stumped...
You can implement this with Ordering type class:
def compare[T : Ordering : Manifest](a: AnyRef, b: AnyRef) = {
val c = manifest[T].erasure
if (c.isAssignableFrom(a.getClass) && c.isAssignableFrom(b.getClass))
implicitly[Ordering[T]].compare(a.asInstanceOf[T], b.asInstanceOf[T])
else
throw new IllegalArgumentException("Wrong argument type")
}
And then use it like this:
compare[Date](new Date, new Date)
compare[String]("A", "B")
But this code will throw IllegalArgumentException:
compare[Date]("A", "B")
If you really don't know types of objects, that you are trying to compare, then you can use this solution:
def compare(a: AnyRef, b: AnyRef) = {
val c = classOf[Comparable[_]]
if (c.isAssignableFrom(a.getClass) && c.isAssignableFrom(a.getClass) && a.getClass == b.getClass) {
a.asInstanceOf[Comparable[AnyRef]].compareTo(b.asInstanceOf[Comparable[AnyRef]])
} else {
throw new IllegalArgumentException("Incopatible argument types: " + a.getClass.getName + " and " + b.getClass.getName)
}
}
It falls down to Java's Comparable interface. Generally scala has 2 traits for this purpose:
Ordred - similar to Comparable, but existing classes (like String or Date) do not implement it, so you can't check it at runtime (at least for these classes)Ordering - it's type class, and you can't retrieve it at runtime.From the other hand Ordered extends Comparable interface, so this solution should also work for all classes that extend Ordered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With