scala - 实现具有隐式功能的蛋糕模式

标签 scala apache-spark

我有一个场景,我想实现一个蛋糕模式的变体,但向一个类(一个 Spark DataFrame)添加隐式功能。

所以,基本上,我希望能够运行如下代码:

trait Transformer {
  this: ColumnAdder =>

  def transform(input: DataFrame): DataFrame = {
    input.addColumn("newCol")
  }
}

val input = sqlContext.range(0, 5)
val transformer = new Transformer with StringColumnAdder
val output = transformer.transform(input)
output.show

并找到如下结果:

+---+------+
| id|newCol|
+---+------+
|  0|newCol|
|  1|newCol|
|  2|newCol|
|  3|newCol|
|  4|newCol|
+---+------+

我的第一个想法是仅在基本特征中定义隐式类:

trait ColumnAdder {
  protected def _addColumn(df: DataFrame, colName: String): DataFrame

  implicit class ColumnAdderRichDataFrame(df: DataFrame) {
    def addColumn(colName: String): DataFrame = _addColumn(df, colName)
  }
}

trait StringColumnAdder extends ColumnAdder {
  protected def _addColumn(df: DataFrame, colName: String): DataFrame = {
    df.withColumn(colName, lit(colName))
  }
}

它有效,但由于函数签名重复,我对这种方法并不完全满意。所以我想到了另一种方法,使用(已弃用?)implicit def战略:

trait ColumnAdder {
  protected implicit def columnAdderImplicits(df: DataFrame): ColumnAdderDataFrame

  abstract class ColumnAdderDataFrame(df: DataFrame) {
    def addColumn(colName: String): DataFrame
  }
}

trait StringColumnAdder extends ColumnAdder {
  protected implicit def columnAdderImplicits(df: DataFrame): ColumnAdderDataFrame = new StringColumnAdderDataFrame(df)

  class StringColumnAdderDataFrame(df: DataFrame) extends ColumnAdderDataFrame(df) {
    def addColumn(colName: String): DataFrame = {
      df.withColumn(colName, lit(colName))
    }
  }
}

(完整的可重现代码,包括一个额外的 trait-module 可以在 here 中找到)

所以,我想问哪种方法是最好的,是否有另一种更好的方法来实现我想要的。

最佳答案

只有两条捷径,但没有什么令人惊讶的:

trait ColumnAdder {
  protected implicit def columnAdderImplicits(df: DataFrame): ColumnAdderDataFrame
  abstract class ColumnAdderDataFrame {
    def addColumn(colName: String): DataFrame
  }
}

trait StringColumnAdder extends ColumnAdder {
  override def columnAdderImplicits(df: DataFrame) =
    new ColumnAdderDataFrame {
      def addColumn(colName: String): DataFrame =
        df.withColumn(colName, lit(colName))
    }
}

如果您愿意启用 -language:reflectiveCalls (请注意含义)然后你也可以写:

trait ColumnAdder {
  protected implicit def columnAdderImplicits(df: DataFrame): {
    def addColumn(colName: String): DataFrame
  }
}

trait StringColumnAdder extends ColumnAdder {
  override def columnAdderImplicits(df: DataFrame) = new {
    def addColumn(colName: String): DataFrame =
      df.withColumn(colName, lit(colName))
  }
}

关于scala - 实现具有隐式功能的蛋糕模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41592343/

相关文章:

apache-spark - Pyspark-将文件从本地(边缘节点)复制到HDFS位置时出错

apache-spark - Spark Streaming forEachBatch 在写入数据库时​​给出不一致/无序的结果

amazon-web-services - 将 Spark 应用程序部署到 EMR 6.x 时应包含哪些依赖项?

scala - 案例分类和特征线性化

multithreading - 在 akka scala Actor 中使用单例

performance - 附加到向量的效率

scala - 如何使用 spark-shell 导入自己的 scala 包?

scala - 使用 Play 生成 <input type ="search"/>!框架

scala - 来自Scala的hdfs连接错误

rest - 使用 SBT 和 Scala 构建 spark-jobserver