2017-01-11 3 views
9

私は、ケーキパターンの変形を実装したいが、暗黙の機能をクラス(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)) 
    } 
} 

それはで動作しますが、このアプローチでは完全に満足していませんでした。なぜなら、関数シグネチャの重複のためです。

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)) 
    } 
    } 
} 

(余分な形質のモジュールを含む完全な再現性のあるコードは、here見つけることができます)

だから、私がお聞きしたかった:だから私は(?非推奨)implicit def戦略を使用して、別のアプローチを考えましたこのアプローチは最高ですが、私が望むものを達成するためのより良い方法があるかもしれません。

答えて

1

ちょうど2つのショートカットが、本当に驚くほど何もない:

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)) 
    } 
} 
関連する問題