2017-12-13 5 views
0

研究プロトタイプでは、プリミティブなScalaデータ型(例:Double)を追加フィールドで拡張したいと考えています。これは、scala.Doublescala.runtime.RichDoublefinalと宣言されているため、すぐに使用することはできません。カスタムスカラライブラリを構築してプリミティブデータ型を拡張する

これは私が試したものです:antを使用して

  1. クローンScalaのリポジトリ

  2. をクラスscala.runtime.RichDoubleからfinal修飾子を削除したファイルでsrc/library/scala/runtime/RichDouble.scala

  3. コンパイルスカラ:ant build-opt

  4. お客様作成RichDouble拡張OMクラス:カスタムコンパイルスカラ座を使用して

    $ echo "class MyDouble extends scala.runtime.RichDouble {}" > MyDouble.scala

  5. コンパイルMyDouble.scala

    $ build/pack/bin/scalac MyDouble.scala

これは、しかし、次のエラーで結果:

MyDouble.scala:1: error: illegal inheritance from final class RichDouble class

で実行

scala-library.jarをコンパイルしたカスタムは確かにロードされている:

$ strace -f ./build/pack/bin/scalac MyDouble.scala 2>&1 | grep scala-library 
stat("/my/custom/dir/scala/build/pack/lib/scala-library.jar", {st_mode=S_IFREG|0664, st_size=5682113, ...}) = 0 

私は何をしないのですか?なぜ修飾子を削除したにもかかわらず、クラスRichDoubleはまだfinalと報告されていますか?

答えて

1

私がやっていることはできません。 Doubleのようなプリミティブ型は、value classesとして実装されており、暗黙的にfinalです。そのように、彼らは拡張することができませんそのessential limitationsの一つです。

+0

Florian、明白な疑問は、あなたが "豊かな"型が標準値クラスから継承しなければならない理由です。 'BigInt'や、あなたの" rich "型が実際に' Number'のようないくつかの特性/インタフェースを実装する普通のクラスである他の同様の型のために使われるアプローチを使わないのはなぜですか? – SergGr

+0

ちょっと、いい点ですが、これについては言及していませんでした。実際にはRichDoubleなどを使用するSparkフレームワークと統合しています。既存のコードベースの大部分を変更したくないです。 – Florian

+0

さて、あなたは運が悪いと思う。 Sparkは性能上の理由から標準値型を​​使用していると思います。 'Float'や' Double'のような型の場合、すべての標準演算は、(インタフェースを介して)いくつかのメソッドのはるかに高価な呼び出しではなく、ただ1つのASM命令で解釈されることが保証されます。 – SergGr

1

implicit classesをご覧ください。閉じたクラスを拡張するように設計されています。

implicit class MyDouble(d: Double) { 
    def myNewFeature() = println("MyDouble is $d") 
} 
val d1 = new Double(42) // just instantiate a Double 
d1.myNewFeature() // scala will do implicit conversion 
+0

私は暗黙のクラスについて知っています。ただし、オブジェクトのシリアル化時にシリアル化される新しいフィールドを追加することはできません。 – Florian

関連する問題