2012-11-07 141 views
2

我想定义一个函数来比较两个类的类型。我已经定义两个不同的类:Scala:比较类型

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

然后我有一个返回Task类型的对象,这可能是要么DefinedTaskEmptyTask的功能。

现在,我想要做的是有标识,如果这个对象是DefinedTask或只是一个EmptyTask的功能。问题很简单,我会使用模式匹配。但我想推广它,因为多个类都采用这种Defined/Empty模式。

我想到目前为止已经试过是:

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总是DefinedTaskT可能是要么DefinedTask or EmptyTask,但它返回为Task

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

这是从编译器的站立点的权利,但它并不适合我。所以,我的问题是我怎么能比较他们的方式,会给我我想要的?

回答

1
  1. 有在你的代码的一些错误:
    • 你应该密封穷举模式匹配
    • 空的情况下,类弃用abstract class Task。编译器应该警告你一下吧。 case object EmptyTask extends Task将是正确的替代方案
  2. 案例类别和案例对象扩展了特征Product。您可以为空与以下任一方式检查产品:
    • task.productArity == 0
    • task.productIterator.isEmpty
  3. 我想你会好得多重新返回你的问题。为什么不只是使用标准Option,并且包含简单的case class Task(id: Int)的实例?这可能是您所有其他类似实体的一般方法。
+0

我已经改写了一些代码,而不是返回EmptyTask,它抛出我在调用函数处理异常。这是一个很好的选择吗? – Andrew

+1

做斯卡拉的推荐方法是一个功能性的方式,而在函数式编程抛出异常作为正常的程序流程的一部分,是一个没有没有。为了在功能上解决这类问题,Scala提供了'Option','Either'和'Try'类型。所以从这个角度来看,不,这不是一个好的选择。但是,如果您必须编写程序,则可以坚持遵循旧的Java约定。 –

+0

我在做什么,实际上是一个网络应用程序。那我怎么知道失败的原因呢? – Andrew

1

它看起来像你想运行时,而不是编译时检查。所以我认为你的意思是

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 
} 

或类似的东西。看看java.lang.Class上的方法,并选择一个你想要的。