2016-04-09 8 views
0

私は形質がこれを好き書き込み:スカラでは、ジェネリックスを指定してケースクラスを拡張する方法はありますか?

trait Extractor[T] { 

    def parse(sc: SparkContext, path: String): RDD[T] 

    def extract(sc: SparkContext, path: String, output: String): Unit = { 
     val rdd = parse(sc, path) 
     val sqlContext = new HiveContext(sc) 
     import sqlContext.implicits._ 
     SaveUtil.saveAsOrc(rdd.toDF(), output) // error 
    } 
} 

私はケースクラスにジェネリックTを任命したい:

case class X(uid: String, app: String, tag: String) 

case class Y(uid: String, dvc: String, tag: String) 

私はScalaのための初心者です。暗黙の変換と共変量は機能していないようです。どうやって?

答えて

1

RDD.toDF()DataFrameHolderへの暗黙的な変換のおかげで存在します。この変換は、以下の署名でmethodにより行われますので、

implicit def rddToDataFrameHolder[A <: Product : TypeTag](rdd: RDD[A]): DataFrameHolder 

- 変換が機能するために:

  • Tは、すべての例のスーパークラスであるProductのサブクラスでなければなりませんクラス(とタプルなど)。
  • 発信者はそう種類T(型消去を克服するために)

のための暗黙のTypeTag持っている必要があります - あなたは基本的に次のようにあなたの形質の宣言を変更したいと思います。しかし

// won't work... 
trait Extractor[T <: Product : TypeTag] { /* unchanged */ } 

をコンテント/ビューの境界を持つ型を持つことはできません。したがって、この宣言は機能しません。ここでは、2つのオプションがあります。

  1. クラスにあなたの形質を変更します(抽象することができます)とTypeTagを追加

    abstract class Extractor[T <: Product : TypeTag] { /* unchanged */ } 
    
  2. extractメソッドに暗黙の引数を追加します。

    trait Extractor[T <: Product] { 
    
        def parse(sc: SparkContext, path: String): RDD[T] 
    
        def extract(sc: SparkContext, path: String, output: String)(implicit evidence: TypeTag[T]): Unit = { /* unchanged */ } 
    } 
    
+0

ありがとう@Tzach Zohar非常に!この問題は完全に解決されました! – jyzheng

+0

喜んで、将来の読者が簡単に見つけることができるように答えを受け入れて+ upvoteしてください –

0
object ExtractorX extends Extractor[X] { 
    override parse(sc: SparkContext, path: String): RDD[X] = ... 
} 

又は

val extractorX = new Extractor[X] { 
    override parse(sc: SparkContext, path: String): RDD[X] = ... 
} 
+0

私は 'extract'コードブロックを再利用したいのですが、' toDF() 'メソッドはRDDにしか適用できません[ケースクラス]。したがって、 'SaveUtil.saveAsOrc(rdd.toDF()、output)'はコンパイル時にエラーが発生します。 – jyzheng

関連する問題