1

我在文件中有以下定义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  

我究竟做错了什么?

4

2 回答 2

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)
}  

你可以试试

以下是要记住的隐含规则(来自 Martin 的书):

这是针对您的特定案例的相关规则(我已突出显示相关部分):

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

于 2019-03-18T13:37:01.960 回答
4

试试这个。。

package com.example

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

object Main extends App {

  println(Show.show(344))
  println(30.show)
}  
于 2019-03-18T13:37:32.567 回答