有什么理由不把Scala隐式地放入一个特征中吗?

有什么理由不把Scala隐式地放入一个特征中吗?,scala,traits,implicit-conversion,Scala,Traits,Implicit Conversion,我开始向代码库添加一些隐式转换。我没有真正研究Scala是如何做到这一点的,也没有看很多例子,所以我将这些作为特性来实现。例如,此代码段允许您测试Spark数据帧的架构: trait DataFrameImplicits { implicit class DataFrameTest(df: DataFrame) { def testInputFields(requiredCols: Map[String, DataType]): Unit = { requiredCo

我开始向代码库添加一些隐式转换。我没有真正研究Scala是如何做到这一点的,也没有看很多例子,所以我将这些作为特性来实现。例如,此代码段允许您测试Spark数据帧的架构:

trait DataFrameImplicits {

  implicit class DataFrameTest(df: DataFrame) {

    def testInputFields(requiredCols: Map[String, DataType]): Unit = {
      requiredCols.foreach { case (colName: String, colType: DataType) =>
        if (!df.schema.exists(_.name == colName) || df.schema(colName).dataType.simpleString != colType.simpleString)
          throw exceptWithLog(DFINPUT_TEST_BADCOLS, s"Input DataFrame to Preprocess.process does not contain column $colName of type ${colType.simpleString}")
      }
    }
然后通过以下方式实现:

object MyFunctionality extends DataFrameImplicits {
    def myfunc(df: DataFrame): DataFrame = {
        df.testInputFields( ??? )
        df.transform( ??? )
    }
}
现在,看看最近更多的Scala代码,我发现包含隐式的“标准”方法是在对象中定义它们并导入它们

import com.package.implicits._
或者类似的


有什么理由把我的代码转换成那样吗?有什么理由不在Scala traits中包含隐式转换吗?

从功能的角度来看,没有区别-隐式转换的行为方式相同

那为什么要对自己施加额外的限制呢?从模块导入隐式通常比扩展特性更简洁。如果你不想让大量的隐式信息充斥你的上下文,你可以导入com.package.implicits.DataFrameTest。对于扩展类和隐式转换,我通常有单独的隐式对象

特性通常用作某些功能的类型边界或封装


顺便说一下,隐式的另一个常见位置是伴随对象。然后它会与您的case类一起自动导入。

我认为这取决于您的偏好,但是在object或Trait中使用隐式会有轻微的区别,因为
object
是单例的,而
traits
不是。我会问相反的问题,为什么要在Trait中使用隐式?-通常,这样做只是为了创建一个聚合对象(如
all
),一次提供所有隐式。但是,你总是通过从一个对象导入它们来获得它们的作用域。@LuisMiguelMejíaSuárez再一次,原因可能是隐含的优先级。@DmytroMitin对,这就是我说“通常”的原因。无论如何,IMHO,隐式优先级是一个复杂的用例。我认为这超出了这个问题的范围。但是,总是值得一提的。不是说“隐式行为会以相同的方式表现”(如果存在多个隐式)。如果导入,则定义与本地隐式具有相同优先级的隐式。如果扩展,则与本地隐式结构相比,会创建低优先级隐式结构。