【发布时间】:2012-09-02 12:56:40
【问题描述】:
显然提取器对象中的 unapply/unapplySeq 不支持隐式参数。假设这里有一个有趣的参数 a,以及一个令人不安的无处不在的参数 b,在提取 c 时会很好地隐藏起来。
[编辑]:似乎我的 intellij/scala-plugin 安装中出现了问题,导致了这种情况。我无法解释。我的智能最近遇到了许多奇怪的问题。重新安装后,我无法再重现我的问题。确认 unapply/unapplySeq 确实允许隐式参数!感谢您的帮助。
这不起作用(**EDIT:是的,它起作用):**
trait A; trait C; trait B { def getC(a: A): C }
def unapply(a:A)(implicit b:B):Option[C] = Option(b.getC(a))
根据我对理想提取器应该是什么样的理解,其中意图对于 Java 人员来说也很直观,这个限制基本上禁止了依赖于附加参数的提取器对象。
您通常如何处理此限制?
到目前为止,我已经有了这四种可能的解决方案:
1)我想改进的最简单的解决方案:不要隐藏b,提供参数b和a,作为元组形式的unapply的普通参数:
object A1{
def unapply(a:(A,B)):Option[C] = Option(a._2.getC(a._1)) }
在客户端代码中:
val c1 = (a,b) match { case A1(c) => c1 }
我不喜欢它,因为这里有更多的噪音偏离将 a 解构为 c 很重要。此外,由于必须说服 Java 人员实际使用此 scala 代码,因此面临着一种额外的语法新颖性(元组大括号)。他们可能会受到反 scala 的攻击“这都是什么?...为什么不首先使用正常方法并检查是否?”。
2) 在封装对特定 B 的依赖的类中定义提取器,导入该实例的提取器。在导入站点对于 java 人来说有点不寻常,但是在模式匹配站点 b 被很好地隐藏了,并且直观地很明显会发生什么。我最喜欢的。我错过了一些劣势?
class BDependent(b:B){
object A2{
def unapply(a:A):Option[C] = Option(b.getC(a))
} }
在客户端代码中的用法:
val bDeps = new BDependent(someB)
import bDeps.A2
val a:A = ...
val c2 = a match { case A2(c) => c }
}
3) 在客户端代码范围内声明提取器对象。 b 是隐藏的,因为它可以在本地范围内使用“b”。妨碍代码重用,严重污染客户端代码(另外,在代码使用前必须说明)。
4) 具有函数 B => C 的 unapply return 选项。这允许导入和使用依赖于参数的提取器,而无需将 b 直接提供给提取器,而是在使用时提供结果。 Java 人可能对函数值的使用感到困惑,b 不是隐藏的:
object A4{
def unapply[A,C](a:A):Option[B => C] = Option((_:B).getC(a))
}
然后在客户端代码中:
val b:B = ...
val soonAC: B => C = a match { case A4(x) => x }
val d = soonAC(b).getD ...
补充说明:
- 正如this answer 中所建议的,“视图边界”可能有助于让提取器处理隐式转换,但这对隐式参数 没有帮助。出于某种原因,我不喜欢使用隐式转换。
- 查看了“上下文边界”,但它们似乎具有相同的限制,不是吗?
【问题讨论】:
标签: scala pattern-matching implicit extractor