为什么找不到隐式?

时间:2019-03-18 13:32:18

标签: scala

我在文件Show.scala中具有以下定义:

package com.example

trait Show[A] {
  def show(a: A): String
}

object Show {
  def apply[A](implicit sh: Show[A]): Show[A] = sh

  //def show[A](a:A)(implicit  sh: Show[A]) = sh.show(a)
  def show[A: Show](a: A) = Show[A].show(a)

  implicit class ShowOps[A: Show](a: A) {
    def show = Show[A].show(a)
  }

  implicit val intCanShow: Show[Int] =
    new Show[Int] {
      override def show(a: Int): String = s"int $a"
    }

}

Main.scala中:

package com.example

object Main extends App {

  println(Show.show(344))
  println(30.show)
}  

编译器抱怨:

[error] /home/developer/scala/show/src/main/scala/com/example/Main.scala:6:14: value show is not a member of Int
[error]   println(30.show)
[error]              ^
[error] one error found  

我在做什么错了?

2 个答案:

答案 0 :(得分:7)

Main找到Show,您需要在import Show._中的Main.scala

package com.example

object Main extends App {
  import Show._ 
  // Or import Show.ShowOps if you only want to use that implicit

  println(Show.show(344))
  println(30.show)
}  

您可以Try it

这里是要记住的implicits rules(摘自Martin的书):

以下是与您的特定案件相关的规则(我已突出显示相关部分):

  

范围规则:插入的隐式转换必须在范围内,作为   单个标识符,或与该标识符的来源或目标类型相关联   转换。 Scala编译器只会考虑隐式   范围内的转化。进行隐式转换   因此,您必须以某种方式将其纳入范围。   此外,除一个例外,隐式转换必须在范围内   作为单个标识符。编译器将不会插入的转换   形式someVariable.convert。例如,它不会扩展x + y   到someVariable.convert(x)+ y。如果你想   someVariable.convert可作为隐式提供,因此,您将   需要导入它,这将使其可以单个使用   标识符。导入后,编译器可以自由地将其应用为   转换(x)+ y。实际上,图书馆通常会包含一个   前导对象,包括许多有用的隐式转换。   然后,使用该库的代码可以执行一个“导入Preamble._”   访问库的隐式转换

答案 1 :(得分:4)

尝试一下。

package com.example

import Show._ // add in order to access implicit..

object Main extends App {

  println(Show.show(344))
  println(30.show)
}