【问题标题】:Scala - implicit conversion with unapplyScala - unapply 的隐式转换
【发布时间】:2011-07-18 17:07:30
【问题描述】:

我想要一个提取器隐式转换其参数,但它似乎不起作用。考虑这个非常简单的案例:

case class MyString(s: String) {}

implicit def string2mystring(x: String): MyString = new MyString(x)
implicit def mystring2string(x: MyString) = x.s

object Apply {
    def unapply(s: MyString): Option[String] = Some(s)
}

但我无法按预期使用它:

val Apply(z) = "a"  // error: scrutinee is incompatible with pattern type

谁能解释为什么无法将参数从String 转换为MyString?我希望它会即时调用string2mystring("a")。显然我可以通过说 val Apply(y) = MyString("a") 来解决这个问题,但我似乎不必这样做。

注意:这个问题类似于this one,但 1)人们并没有很好地回答为什么会发生这种情况,2)这个例子比它需要的更复杂。

【问题讨论】:

    标签: scala implicit-conversion unapply


    【解决方案1】:

    模式匹配时不应用隐式转换。这不是您的代码的错误或问题,它只是 Scala 的创建者的设计决定。

    要修复它,您应该编写另一个接受 String 的提取器——这反过来又可以调用您的隐式转换。

    或者,您可以尝试使用视图绑定,这似乎也可以,并且如果您稍后将其他隐式转换定义为MyString,也可以:

    object Apply {
      def unapply[S <% MyString](s: S): Option[String] = Some(s.s)
    }
    

    【讨论】:

    • 谢谢。这有点令人失望。你知道这个决定的动机是什么吗?
    • 是的,将def unapply(p: String): Option[String] = Some(p) 添加到Apply 就可以了。所以我会同意的。谢谢。
    • @dhg 我编辑了答案——视图绑定似乎也可以。
    • 太棒了!视图绑定是一个很好的解决方案。它不仅不需要为每种可能的类型编写额外的方法,而且还解决了我遇到的另一个问题:如果unapply 接受一个元组,由于类型擦除,你不能使用重载技巧。但这可以干净地解决它并导致错误 arg 类型的编译时错误:def unapply[S &lt;% MyString](p: (S, Int)): Option[String] = Some(p._1.s + p._2).
    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 2018-02-01
    • 2019-04-01
    • 1970-01-01
    • 2012-04-15
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多