我有一个场景,我想实现一个蛋糕模式的变体,但向一个类(一个 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/