重载unapply和子类

时间:2016-08-21 20:25:05

标签: scala

通常,如果我们有一个参数类型为A的提取器,并且我们使用它来匹配类型为B >: A的对象,则首先检查该对象是否为{的实例在传递给提取程序A之前{1}}:

unapply

致电trait Foo class SomeFoo extends Foo object FooBar { def unapply(foo: SomeFoo) = true } def foo(foo: Foo): Unit = foo match { case FooBar() => println("ok") } 时应打印foo(new SomeFoo)

但是如果我们在FooBar中重载方法ok,它就不再起作用了:

unapply

我们收到错误:

object Test {

  trait Foo
  class SomeFoo extends Foo

  trait Bar
  class SomeBar extends Bar

  object FooBar {
    def unapply(foo: SomeFoo) = true
    def unapply(bar: SomeBar) = true
  }

  def foo(foo: Foo): Unit = foo match {
    case FooBar() => println("foo")
    case _        =>
  }

  def bar(bar: Bar): Unit = bar match {
    case FooBar() => println("bar")
    case _        =>
  }

  def main(args: Array[String]): Unit = {
    foo(new SomeFoo)
    bar(new SomeBar)
  }
}

overloaded method value unapply with alternatives: (bar: Test.SomeBar)Boolean <and> (foo: Test.SomeFoo)Boolean cannot be applied to (Test.Foo) case FooBar() => println("foo") 相似。

删除Bar方法中的任何一种或将unapplyfoo中的参数类型更改为barSomeFoo即可解决此问题。

为什么?编译器不应该能够选择正确的方法吗?我了解重载SomeBar可能会导致歧义(例如unapplyunapply(Foo)),但这种情况并非如此。

我想做这样的事情:

unapply(SomeFoo)

然后像这样使用它:

trait Term
case class Var(name: String) extends Term
case class Lambda(x: Var, e: Term) extends Term
case class Apply(f: Term, a: Term) extends Term

trait TypedTerm
case class TypedVar(name: String) extends TypedTerm
case class AnnotatedVar(v: TypedVar, t: Type) extends TypedTerm
case class TypedLambda(x: AnnotatedVar, e: TypedTerm) extends TypedTerm
case class TypedApply(f: TypedTerm, a: TypedTerm) extends TypedTerm

object !: {
  def unapply(t: TypedLambda) = TypedLambda.unapply(t)
  def unapply(t: Lambda) = Lambda.unapply(t)
}

object % {
  def unapply(t: TypedApply) = TypedApply.unapply(t)
  def unapply(t: Apply) = Apply.unapply(t)
}

object :: {
  def unapply(v: AnnotatedVar) = AnnotatedVar.unapply(v)
}

也许有不同的解决方案?

0 个答案:

没有答案