隐含范围

时间:2017-07-07 12:04:28

标签: scala implicit

我有一个特性




  trait Tr {
 def逻辑:选项[()=>单位] =无
 def apply():单位=逻辑匹配{
 case Some(l)=>升()
 case None =>
 }
}

对象Tr {
隐式def procLogic2Opt(processingLogic :()=> Unit):选项[()=>单位]
 =一些(processingLogic)
}
  




当我必须导入特征的子类时 Tr ._ 明确地将implicits带入范围。像这样




 导入Tr._ //否则不编译

类Trrr扩展Tr {
覆盖def处理Logic =()=> println(“test”)
}
  




有没有办法在没有明确导入的情况下执行此操作?我怎么能重新设计呢?




2 个答案:

答案 0 :(得分:3)

回答标题问题,如果你真的真的需要它,请将你的隐性转移到特质:

trait Tr{
    implicit def procLogic2Opt(...) = ...
}

但这并不总是一种好的做法,因为很难找到哪种隐含的责任。

一个故事:在我以前的项目中,我们使用隐式(种类)T => Any来记录特征,这是我们在任何地方继承的 - 想象我们有多少意外的类型转换。同样适用于() => Unit,因为很多人可能会继承你的特性,甚至不知道你的隐含和奇怪为什么除了apply之外的其他函数不应该工作。

除了隐式转换(例如您的procLogic2Opt)也是一种不良做法(几乎总是如此)。

引自here

  

不要使用implicits在类似之间进行自动转换   数据类型(例如,将列表转换为流);这些是   明确地做得更好,因为类型具有不同的语义,和   读者应该注意这些含义。

更确切地说,关于您的案例:Scala Option implicit conversion - Bad practice or missing feature?

改为使用隐式类:

implicit class RichSomething(something: Something){
  def toSomethingElse = ...
}

something.toSomethingElse

如评论中所述,您的案例更简单

Some(() => println("aaaa"))

class Trrr extends Tr{
   override def logic = Some(() => println("test"))
}

这会为您提供明确,易于理解和可发现的类型,而不会想知道() => Unit如何成为Option[() => Unit]

答案 1 :(得分:1)

  

因为客户端应该只调用apply。我认为子类无需知道Option是必需的

那么,为什么需要呢?

trait Tr {
    protected val logic: () => Unit = () => {}
    def apply(): Unit = logic()
}

class Trrr extends Tr{
   override val logic = () => println("test")
}

val logic以避免每次都重新创建它。)