将隐式引入范围

Bring implicit to scope

我有一个特点

trait Tr{
    def logic: Option[() => Unit] = None
    def apply(): Unit = logic match {
         case Some(l) => l()
         case None =>
    }
}

object Tr{
    implicit def procLogic2Opt(processingLogic: () => Unit): Option[() => Unit] 
= Some(processingLogic)
}

问题是在对特征进行子类化时,我必须显式导入 Tr._ 以将隐含项引入范围。像这样

import Tr._ //otherwise does not compile

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

有没有不用显式导入的方法?我该如何重新设计它?

回答标题问题,如果你真的真的真的需要它,把你的隐式移到特征:

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

虽然这并不总是一个好的做法,因为很难找到哪个隐式负责。

一个故事:在我之前的项目中,我们在任何地方都继承了具有隐式(某种)T => Any 的日志记录特征 - 想象一下我们有多少意想不到的类型转换。 () => Unit 也是如此,因为很多人可能会继承你的特质,甚至不知道你的隐式,并且想知道为什么 apply 以外的功能在它们不应该工作的时候工作。


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

引自here

Do not use implicits to do automatic conversions between similar datatypes (for example, converting a list to a stream); these are better done explicitly because the types have different semantics, and the reader should beware of these implications.

更准确地说你的情况:Scala Option implicit conversion - Bad practice or missing feature?

改用implicit-classes:

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]

Because the client is supposed to call only apply. I thought it's not necessary for subclassers to know that Option is required

那么,为什么需要它?

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

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

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