【问题标题】:Scala implicit conversion from parent traitScala 从父 trait 隐式转换
【发布时间】:2016-01-22 23:58:59
【问题描述】:

以下代码无法编译:

import scala.language.implicitConversions

trait Base {
  class Wrp[+T](val v: T) // wrapper / internal representation
}

trait BooleanOps extends Base {
  // implicit conversion
  implicit def lift2BooleanOpsCls(x: Boolean): BooleanOpsCls =
    new BooleanOpsCls(new Wrp[Boolean](x))
  class BooleanOpsCls(wx: Wrp[Boolean]) {
    def ||(wy: =>Wrp[Boolean]): Wrp[Boolean] = new Wrp[Boolean](wx.v || wy.v)
  }
}

trait MyExample extends BooleanOps {
  // test method
  def foo(): Wrp[Boolean] = {
    val ret: Wrp[Boolean] = false || new Wrp[Boolean](true)
    ret
  }
}

输出:

MyExample.scala:18: error: type mismatch;
 found   : MyExample.this.Wrp[Boolean]
 required: Boolean
        val ret: Wrp[Boolean] = false || new Wrp[Boolean](true)
                                         ^

但如果我:

1) 将 class Wrp 放在 Base 之外

2) 将BooleanOps 的主体移动到MyExample

一切都会编译。

为什么原始示例不起作用?如果您对此行为有所了解,我们将不胜感激。谢谢。

【问题讨论】:

    标签: scala implicit-conversion implicit traits


    【解决方案1】:

    一个问题是def ||(wy: =>Wrp[Boolean]) 中参数的名称调用性质
    如果你把它改写成def ||(wy: Wrp[Boolean]) 就可以了

    但我同意,如果您在 Wrp 或 BooleanOpsCls 周围移动它会起作用,这很奇怪!隐式解析的意图或错误??

    【讨论】:

    • 太好了,我可以确认这是可行的。谢谢 :) 问题仍然是原始示例中到底发生了什么,也与提出的两种解决方法有关。
    • @perovic 只是@cbastin 答案上下文中的想法:我假设由于按名称调用参数的性质,隐式搜索的方式不同,因为=>Wrp[Boolean] 是一段代码而不是比类型。因为那个编译器不认为这个方法定义在隐式搜索期间是适用的。不幸的是,我无法通过任何可靠的来源证实这一点,所以这是一个完全疯狂的猜测。但是考虑到这种行为很奇怪并且取决于Wrp 的定位,它看起来像一个错误,我想它值得作为编译器团队的jira 票发布吗?
    • @Archeg 谢谢你的建议。似乎许多元素和规则在相互作用。我仍然不确定这是一个错误,所以我会再等一会儿,希望有人能够给出完整的解释。
    【解决方案2】:

    如果您重命名 || 方法,原始示例将起作用。编译器会找到 false.||() 方法,并且不会费心去寻找可能在那里工作的隐式方法。

    【讨论】:

    • 确实,这行得通,但我试图重载|| 运算符的行为。编译器找到同名的方法(||),但参数类型不同(Wrp[Boolean]而不是Boolean),所以它应该执行隐式搜索。如果我将隐式转换放在MyExample 的主体中,或者如果我将class Wrp 定义放在Base 之外,这确实会发生,如问题中所述。我不明白为什么这些解决方案有效而原始示例无效。
    【解决方案3】:

    问题在于没有一个名为Wrp 的类(暂时忽略T)——Base 没有定义Wrp,而是定义了每个类的命名子类扩展Base 的具体 类。隐含的东西也是一条红鲱鱼。赠品的错误是提到了MyExample.this.Wrp——请记住,即使MyExample 也没有这样的类——val x = new MyExample 的类型为Object with MyExample

    【讨论】:

    • 感谢罗布的回答。在实际代码中Wrp是一个抽象类型,我这里做了简化。但是,如果|| 运算符的Wrp[Boolean] 参数是按值调用,或者如果我将隐式转换(implicit defclass)放在 MyExample 特征中,该示例仍然有效。你知道这与你的答案有什么关系吗?
    • 我不确定...也许您可以添加一个额外的替代最小示例?
    猜你喜欢
    • 2018-09-25
    • 2012-04-15
    • 2018-09-16
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多