声明一个接受未知案例类作为参数的方法,以便在Scala中的模式匹配中使用它

时间:2012-04-15 18:26:10

标签: scala methods pattern-matching arguments case-class

想象一个抽象的A类,它有一组case类。我们不知道有多少集合类,甚至不知道这些案例类的名称。

abstract class A(field: String)
//Example of a case class that extends A
case class B(f: String) extends A(f)

现在我有了这个:

a match {
    case B(f) => println("f")
}

我想通过参数将case类类型传递给方法。我想要这个的原因是因为我将在文件中配置一组规则。我想加载这些规则并使用模式匹配与这些规则提供的一些信息。我想做这样的事情:

def printer (a: A, B: A) = {
   a match{
       case B(f) => println("f")
   }
}

这可能吗?

如果不是那么容易,我可以在模式匹配中使用抽象类吗?如果我可以简单地使用抽象类,那将是完美的,因为它具有所有案例类的主要结构。

编辑:

忘记提到案例类可以有不同的参数,所以最好使用基于类A的东西(因为我可以只使用字段匹配模式)

3 个答案:

答案 0 :(得分:5)

不像你试过的那样。但是如果你使用 Manifest 作为上下文绑定,你可以使它工作:

scala> trait Foo
defined trait Foo

scala> case class Bar(baz: String) extends Foo
defined class Bar

scala> def boo[A <: Foo : Manifest](foo: Foo) =
     |   if (foo.getClass isAssignableFrom manifest[A].erasure) "foo" else "boo"
boo: [A <: Foo](foo: Foo)(implicit evidence$1: Manifest[A])java.lang.String

scala> boo[Foo](Bar(""))
res0: java.lang.String = boo

scala> boo[Bar](Bar(""))
res1: java.lang.String = foo

答案 1 :(得分:1)

您可以从案例类的随播对象中提取unapply方法并使用它:

scala> :paste
// Entering paste mode (ctrl-D to finish)

abstract class A(field: String)
case class B(f: String) extends A(f)
case class C(f: String) extends A(f)
case class E(f: String, f1: Int) extends A(f)
case class F(f: String, f1: Int) extends A(f)

class Unapplyer[T: Manifest, R](f: T => Option[R]) {
  def unapply(a: Any): Option[R] = {
    if (manifest[T].erasure.isInstance(a)) f(a.asInstanceOf[T]) else None
  }
}

def printer[T: Manifest, R](a: A, b: T => Option[R]) {
  val P = new Unapplyer(b)
  a match {
    case P((f, f1)) => println(f + " - " + f1)
    case P(f) => println(f)
    case _ => println("oops")
  }
}

// Exiting paste mode, now interpreting.

defined class A
defined class B
defined class C
defined class E
defined class F
defined class Unapplyer
printer: [T, R](a: A, b: (T) => Option[R])(implicit evidence$2: Manifest[T])Unit

scala> printer(B("test"), B.unapply _ )
test

scala> printer(B("test"), C.unapply _ )
oops

scala> printer(E("test", 1), E.unapply _ )
test - 1

scala> printer(E("test", 1), F.unapply _ )
oops

scala> printer(E("test", 1), B.unapply _ )
oops

UPD:使用变量编号和参数类型添加了用法。

答案 2 :(得分:0)

我不明白为什么要将类型传递给方法。使用模式匹配时,无论如何都要检查类型。那么为什么要传递呢? 你可以写

abstract class A(field: String)
case class B(f: String) extends A(f)
case class C(i: Int) extends A(i.toString)

def printer (a: A) = {
   a match{
       case B(f) => println(f)
       case C(i) => println(i)
   }
}