Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 模式匹配与泛型_Scala - Fatal编程技术网

Scala 模式匹配与泛型

Scala 模式匹配与泛型,scala,Scala,给定以下类模式匹配: clazz match { case MyClass => someMethod[MyClass] } 是否可以根据模式匹配的结果以通用方式引用MyClass?例如,如果我有MyClass的多个子类,我可以编写一个简单的模式匹配来将匹配的类型传递给someMethod: clazz match { case m <: MyClass => someMethod[m] } clazz匹配{ 案例m方法[m] } 不幸的是,类型在Scala中并不是

给定以下类模式匹配:

clazz match {
  case MyClass => someMethod[MyClass]
}
是否可以根据模式匹配的结果以通用方式引用MyClass?例如,如果我有MyClass的多个子类,我可以编写一个简单的模式匹配来将匹配的类型传递给
someMethod

clazz match {
  case m <: MyClass => someMethod[m]
}
clazz匹配{
案例m方法[m]
}

不幸的是,类型在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
}
因此,如果你想挽救自己严重的大脑损伤,我会忘记这个项目,或者寻找另一种语言。也许哈斯克尔在这里更好?我仍然希望我们能最终匹配类型,但我的希望很低


也许scalaz的人已经想出了一个解决方案,他们几乎将Scala的类型系统开发到了极限。

您的代码并不十分清晰,因为至少在java
clazz
中,clazz是
java.lang.Class
类型变量和变体的典型名称。我仍然相信
clazz
不是
Class
的例子,而是你自己的类的例子


在Java和Scala中,给定一个对象o:AnyRef,您可以在运行时通过
o.getClass:class[\u]
访问它的类,例如通过反射API创建该类的实例。但是,类型参数是在编译时传递的,所以不能像在编译时那样传递类型。您可以在所有地方使用
AnyRef
作为类型(我认为这会起作用),或者如果您有更高级的需求,可以使用反射API。

Meh。我认为“忘记这个项目或寻找另一种语言”从这个例子来看有点极端,它反映了我对尝试实现类似目标的沮丧。我花了几周的时间进行永久性重构,却没有找到可行的解决方案。因此,我在此建议不要重复这一经验,并确保一个月的工作安全。您的代码无法工作,因为
canCarry
需要一个非隐式参数,因此难怪它从未应用过。但是,有一个解决方案:我建议您将
MaybeCarry
替换为
OptManifest
NoCarry
替换为
NoManifest
,并将
Carry
替换为
Manifest
(我看到两者之间的区别主要在于
equals
的实现)。它闻起来像是
清单
,但因为它只让我们完成一个不可能的答案,而不给其他选项留出空间,所以我不得不对“我可以编写一个简单的模式匹配来传递匹配的类型”说“不”。
test[String]
test[PayLoad]  // ouch, not doin it
test[PayLoad](new Carry[PayLoad])  // sucks