以下代码不起作用:
trait A {
type C
val Extract: {
def unapply(c: C): Option[Int]
}
}
错误如下:
错误:结构细化中的参数类型可能不会引用在该细化之外定义的抽象类型
我想写上面的内容,以便强制特质A的用户定义一个具有unapply
方法的对象或值,以便我可以在模式匹配中使用它。
我找到了两个解决方法,感谢"Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"和Scala: "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"(见下文),但第一个是强制性的继承,如果我尝试链接到外部库,这是不可行的;而对于第二种情况,我放弃了覆盖Extract
以更多方法的可能性。
变通方法
trait A {
type C
trait Extractable {
def unapply(c: C): Option[Int]
}
val Extract: Extractable
}
trait A {
type C
def extract(c: C): Option[Int]
object Extract {
def unapply(c: C): Option[Int] = extract(c)
}
}
有没有办法(可能不是结构类型)我可以表达用户可以按照他想要的方式实现Extract
的想法,只要它有所请求签名的方法unapply
?
答案 0 :(得分:1)
你考虑过类型课吗? A
只是声明其类型参数必须是“可提取的”,也就是说,范围中必须存在类型为Extractable[C]
的隐式值(这只需要您实现unapply
)。这可以来自您,来自其他一些图书馆或来自用户本人。
但这意味着,对于给定类型Extractable[C]
,您不能同时拥有多个C
;也就是说,对于某些给定类型Extractable
(例如C
),Int
只有一个实现。这与您的用例一致吗?
trait Extractable[C] {
def unapply(c: C): Option[Int]
}
// user can supply his own extractable:
implicit val myExtractableInt = new Extractable[Int] {
def unapply(c: Int): Option[Int] = Some(c)
}
// class A is parameterized by some C
// for which Extractable[C] must exist
class A[C : Extractable] {
val c: C = ???
implicitly[Extractable[C]].unapply(c)
}
编辑:
要使A
成为特征,我们需要一个(又一个)解决方法:
trait Extractable[C] {
def unapply(c: C): Option[Int]
}
// class A is parameterized by C
// for which Extractable[C] must exist
trait A[C] {
implicit def e: Extractable[C]
val c: C = ???
e.unapply(c)
}
class SomeClass extends A[Int] {
// we need an implicit Extractable[Int],
// either from some import or custom one
implicit def e = new Extractable[Int] {
def unapply(c: Int): Option[Int] = Some(c)
}
}