複数のコンストラクターを持つJavaクラスがあるとします:
class Base {
Base(int arg1) {...};
Base(String arg2) {...};
Base(double arg3) {...};
}
Scalaで拡張し、Baseの3つのコンストラクターすべてへのアクセスを提供するにはどうすればよいですか?Scalaでは、サブクラスはそのスーパークラスのコンストラクターの1つしか呼び出すことができません。このルールを回避するにはどうすればよいですか?
Javaクラスは、変更できないレガシーコードであると想定します。
特性がクラスを拡張する可能性があることを忘れがちです。トレイトを使用する場合は、次のように、呼び出すコンストラクターの決定を延期できます。
trait Extended extends Base {
...
}
object Extended {
def apply(arg1: Int) = new Base(arg1) with Extended
def apply(arg2: String) = new Base(arg2) with Extended
def apply(arg3: Double) = new Base(arg3) with Extended
}
トレイト自体にコンストラクターパラメーターがない場合もありますが、代わりに抽象メンバーを使用することで回避できます。
[〜#〜] edit [〜#〜]-これは私が思ったscalaメーリングリストの質問からです私の答えは、3つの異なるコンストラクターを提供すること(つまり、Javaデザイン)を複製すること)と、クラスを拡張しないことに関するものです。
各コンストラクターが最終的にオブジェクトのstateS
を作成すると仮定して、これを作成するための「静的」メソッドを使用してコンパニオンオブジェクトを作成します状態
object Base {
private def stateFrom(d : Double) : S = error("TODO")
private def stateFrom(s : Str) : S = error("TODO")
private def stateFrom(i : Int) : S = error("TODO")
}
次に、状態を取得するプライベートコンストラクターと、プライマリコンストラクターに従う(パブリック)オーバーロードコンストラクターを作成します。
import Base._
class Base private(s : S) { //private constructor takes the state
def this(d : Double) = this(stateFrom(d))
def this(str : String) = this(stateFrom(str))
def this(i : Int) = this(stateFrom(i))
//etc
}
これはばかげた答えであり、おそらくある程度は機能しますが、Javaクラスのコンストラクターが多すぎる場合は、手間がかかりすぎる可能性がありますが、次のようになります。
Javaにサブクラスを記述します。このコンストラクターは、他のさまざまなコンストラクターが行うすべての入力を受け取り、入力の有無に基づいてスーパークラスの適切なコンストラクターを呼び出します( "nullの使用による) "またはある種の番兵値)、次にそのJavaクラスin Scala)をサブクラス化し、番兵値をデフォルトパラメーターとして割り当てます。
最も一般的なもの(この場合はString)を選択し、他の基準を満たしている場合は自分で内部変換を行います。
私はこれが最善の解決策ではないことを認めますが、何かがそれについて間違っていると私は思います。 :-(