通常,如果我们有一个参数类型为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
方法中的任何一种或将unapply
和foo
中的参数类型更改为bar
和SomeFoo
即可解决此问题。
为什么?编译器不应该能够选择正确的方法吗?我了解重载SomeBar
可能会导致歧义(例如unapply
与unapply(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)
}
也许有不同的解决方案?