2017-01-11 7 views
9

मेरे पास एक परिदृश्य है जहां मैं केक पैटर्न का एक संस्करण लागू करना चाहता हूं, लेकिन एक वर्ग (स्पार्क डेटाफ्रेम) के लिए अंतर्निहित कार्यक्षमता जोड़ना चाहता हूं। करने के लिएनिहित कार्यक्षमता के साथ एक केक पैटर्न को कार्यान्वित करना

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

मेरा पहला विचार था:

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 

तरह निम्नलिखित एक परिणाम और पाते हैं:

तो, मूल रूप से, मैं निम्नलिखित की तरह एक कोड को चलाने के लिए सक्षम होना चाहते हैं केवल मूल लक्षणों में निहित कक्षाओं को परिभाषित करें:

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

(पूर्ण प्रतिलिपि प्रस्तुत करने योग्य कोड, एक अतिरिक्त विशेषता मॉड्यूल सहित here पाया जा सकता है)

तो, मैं पूछना चाहता था कौन सा दृष्टिकोण सबसे अच्छा है और यदि मैं जो चाहता हूं उसे हासिल करने का एक और बेहतर तरीका हो सकता है।

उत्तर

1

सिर्फ दो शॉर्टकट, लेकिन वास्तव में आश्चर्यजनक कुछ भी नहीं:

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)) 
    } 
} 
संबंधित मुद्दे