Andrew
Andrew

Reputation: 6404

Scala: Compare types

I want to define a function that could compare two class types. I have defined two different classes:

abstract class Task
case class DefinedTask(id: Long) extends Task
case class EmptyTask() extends Task  

Then I have a function that returns an object of type Task, that could be either DefinedTask or EmptyTask.

Now, what I'd like to do is to have a function that identifies if this object is a DefinedTask or just an EmptyTask. The problem would be simple, I'd use pattern matching. But I want to generalize it because multiple classes go with this Defined/Empty pattern.

What I'd tried so far is:

def makeReturned[T: Manifest, U: Manifest](obj: T)(u: U)(f: T => Value) = 
   if(manifest[U] equals manifest[T]) f(obj) else
     throw new IllegalArgumentException()
}
//call to it
makeReturned(task)(DefinedTask)(makeTask)

U is always DefinedTask, T could be either DefinedTask or EmptyTask, but it is returned as Task.

manifest[U].erasure.toString //"class DefinedTask$"
manifest[T].erasure.toString //"class Task"  

Which is right from the compiler's stand point but it's not for me. So, my question is how could I compare them in a way that would give me what I want?

Upvotes: 3

Views: 5534

Answers (2)

Nikita Volkov
Nikita Volkov

Reputation: 43350

  1. There are some mistakes in your code:
    • You should make the abstract class Task sealed for exhaustive pattern matching
    • Empty case classes are deprecated. The compiler should have warned you about it. case object EmptyTask extends Task would be the correct alternative
  2. Both case classes and case objects extend the trait Product. You can check the product on being empty with either of the following ways:
    • task.productArity == 0
    • task.productIterator.isEmpty
  3. I think you'd be much better off reapproaching your problem. Why not just use the standard Option and have the instances of a simple case class Task(id: Int) wrapped in it? This could be the general approach for all the other similar entities of yours.

Upvotes: 1

Rex Kerr
Rex Kerr

Reputation: 167921

It looks like you want run-time, not compile-time checking. So I think you mean

def makeReturned[U <: Task, T <: Task](obj: T)(u: U)(f: T => Value) = {
  if (obj.getClass.isInstance(u.getClass)) f(obj)
  else throw new IllegalArgumentException
}

or something like that. Look at the methods on java.lang.Class and pick the one that does what you want.

Upvotes: 2

Related Questions