私は、既存のJavaライブラリー用の暗黙のScalaラッパー・クラスのセットを作成しています (そのライブラリーを装飾して、 Scala開発者にとってより便利なものにすることができます)。
簡単な例として、Javaライブラリ (私は変更できません) に次のようなクラスがあるとします。
public class Value<T> {
// Etc.
public void setValue(T newValue) {...}
public T getValue() {...}
}
ここで、このクラスをScalaスタイルのゲッターとセッターで装飾したいとしましょう。これは、次の暗黙のクラスで行うことができます。
final implicit class RichValue[T](private val v: Value[T])
extends AnyVal {
// Etc.
def value: T = v.getValue
def value_=(newValue: T): Unit = v.setValue(newValue)
}
このimplicit
キーワードは、ScalaValue
コンパイラーに、 のインスタンスを のインスタンスにRichValue
暗黙的に変換できることを伝えます (後者がスコープ内にある場合)。これで、内で定義されたメソッドRichValue
を のインスタンスに適用できるようになりValue
ました。例えば:
def increment(v: Value[Int]): Unit = {
v.value = v.value + 1
}
(これはあまり良いコードではなく、正確に機能するわけでもありません。単純な使用例を示しているだけです。)
残念ながら、Scalaimplicit
ではクラスをトップレベルにすることは許可されていないためpackage object
、. (この制限が必要な理由はわかりませんが、暗黙の変換関数との互換性のためだと思います。)object
class
trait
package
ただし、これを値クラスRichValue
にするためにからも拡張しています。それらに慣れていない場合は、Scalaコンパイラーが割り当ての最適化を行うことができます。特に、コンパイラは常に のインスタンスを作成する必要はなく、値クラスのコンストラクタ引数を直接操作できます。AnyVal
RichValue
言い換えれば、Scala の暗黙的な値クラスをラッパーとして使用することによるパフォーマンスのオーバーヘッドはほとんどなく、これは素晴らしいことです。:-)
ただし、値クラスの主な制限は、class
またはtrait
;内で定義できないことです。package
s、package object
s、またはs のメンバーにしかなれませんobject
。(これは、外部クラス インスタンスへのポインタを維持する必要がないようにするためです。)
暗黙の値クラスは両方の制約セットを尊重する必要があるため、package object
または内でのみ定義できますobject
。
そしてそこに問題があります。私がラップしているライブラリには、膨大な数のクラスとインターフェースを持つパッケージの深い階層が含まれています。import
理想的には、次のような単一のステートメントで
ラッパー クラスをインポートできるようにしたいと考えています。
import mylib.implicits._
それらをできるだけ簡単に使用できるようにします。
これを達成するために私が現在確認できる唯一の方法は、すべての暗黙的な値クラス定義を 1つのソース ファイル内の 1
つのpackage object
(または) 内に配置することです。object
package mylib
package object implicits {
implicit final class RichValue[T](private val v: Value[T])
extends AnyVal {
// ...
}
// Etc. with hundreds of other such classes.
}
import
ただし、これは理想とはほど遠いものであり、ターゲット ライブラリのパッケージ構造をミラーリングしながら、1 つのステートメントですべてをスコープに含めたいと考えています。
このアプローチの利点を犠牲にすることなく、これを達成する簡単な方法はありますか?
(たとえば、これらのラッパーを値クラスtrait
にするのをやめると、コンポーネント パッケージごとに 1 つずつ、多数の異なる s 内でそれらを定義し、ルートpackage object
にそれらすべてを拡張させて、単一のインポートしますが、利便性のためにパフォーマンスを犠牲にしたくありません。)