2011-03-19 75 views
3

匹配:模式与给定下面的类模式匹配泛型

clazz match { 
    case MyClass => someMethod[MyClass] 
} 

是否有可能是指MyClass的基于什么模式匹配想出了一个通用的方法?举例来说,如果我有MyClass的多个子类,我可以写一个简单的模式匹配的匹配系传递到someMethod

clazz match { 
    case m <: MyClass => someMethod[m] 
} 
+1

它闻起来像'Manifest',但只是让我们完成一个不可能的答案,而不让其他选项空间,我不得不说“我可以写一个简单的模式匹配来传递匹配的类型”。 – shellholic 2011-03-22 10:21:44

回答

7

可惜类型是不是真的在Scala中的一等公民。这意味着例如你不能对类型进行模式匹配。由于从Java平台继承的愚蠢类型擦除导致大量信息丢失。

我不知道是否有任何改善要求,但这是我的选择中最糟糕的问题之一,所以有人应该真的想出这样的要求。

事实是,您将需要传递证据参数,最好以隐式参数的形式传递。

我能想到的最好进去的

class PayLoad 

trait LowPriMaybeCarry { 
    implicit def no[C] = new NoCarry[C] 
} 
object MaybeCarry extends LowPriMaybeCarry { 
    implicit def canCarry[C <: PayLoad](c: C) = new Carry[C] 
} 

sealed trait MaybeCarry[C] 
final class NoCarry[C] extends MaybeCarry[C] 
final class Carry[C <: PayLoad] extends MaybeCarry[C] { 
    type C <: PayLoad 
} 

class SomeClass[C <: PayLoad] 

def test[C](implicit mc: MaybeCarry[C]) : Option[SomeClass[_]] = mc match { 
    case c: Carry[_] => Some(new SomeClass[ c.C ]) 
    case _ => None 
} 

行但我仍然不能得到implicits工作:

test[String] 
test[PayLoad] // ouch, not doin it 
test[PayLoad](new Carry[PayLoad]) // sucks 

所以,如果你想保存自己浆液性脑损坏,我会忘记项目或寻找另一种语言。也许Haskell在这里更好?我仍然希望我们能够最终匹配类型,但我的希望非常低。

也许来自scalaz的人提出了一个解决方案,他们几乎将Scala的类型系统用于极限。

+2

呃。我认为,“忘记项目或者寻找另一种语言”在这个例子中有点极端^^ – 2011-03-20 01:16:12

+1

好吧,这反映了我对尝试实现类似的东西感到沮丧。花费我几个星期的永久重构,而没有达到一个可行的解决方案。所以我建议在这里不要重复这个经历和一个月的工作安全。 – 2011-03-20 02:11:51

+0

你的代码不能工作,因为'canCarry'需要一个非隐式参数,因此难怪它永远不会被应用。 然而,存在一个解决方案:我建议你用'OptManifest'替换'MaybeCarry',用NoManifest替换'NoCarry'和用'Manifest' /'ClassManifest'替换'(我看到的区别主要在于执行'equals')。 – Blaisorblade 2011-09-21 16:22:34

0

你的代码是不是真的清楚,因为至少在Java clazzjava.lang.Class类型和变化的变量,一个典型的名称。我仍然认为clazz不是Class的实例,而是您自己班的实例。

在Java和Scala中,给定一个对象o:AnyRef,您可以在运行时通过o.getClass: Class[_]访问其类,并且可以通过Reflection API创建该类的实例。但是,类型参数是在编译时传递的,因此您无法在编译时按原样传递类型。要么你使用AnyRef作为类型(这将工作,我假设),或者如果你有更高级的需求,你使用反射API。