Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast objects to comparable type

Tags:

scala

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...

like image 227
Andres Avatar asked Dec 20 '25 22:12

Andres


1 Answers

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") 

Update

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.

like image 151
tenshi Avatar answered Dec 22 '25 13:12

tenshi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!