60

複数のコンストラクターを持つJavaクラスがあるとします。

class Base {
    Base(int arg1) {...};
    Base(String arg2) {...};
    Base(double arg3) {...};
}

Scalaで拡張し、Baseの3つのコンストラクターすべてへのアクセスを提供するにはどうすればよいですか?Scalaでは、サブクラスはそのスーパークラスのコンストラクターの1つのみを呼び出すことができます。このルールを回避するにはどうすればよいですか?

Javaクラスは、変更できないレガシーコードであると想定します。

4

4 に答える 4

94

特性がクラスを拡張する可能性があることを忘れがちです。トレイトを使用する場合は、次のように、呼び出すコンストラクターの決定を延期できます。

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
}

トレイト自体にコンストラクターパラメーターがない場合もありますが、代わりに抽象メンバーを使用することで回避できます。

于 2010-07-21T13:40:02.007 に答える
5

編集-これは、私がここで複製されたと思ったscalaメーリングリストの質問からのものです。私の答えは、3つの異なるコンストラクターを提供すること(つまり、Java設計を複製すること)に関連しており、クラスを拡張しないことに関するものです。

各コンストラクターが最終的にオブジェクトの状態 を作成すると仮定して、Sこの状態を作成するための「静的」メソッドを使用してコンパニオンオブジェクトを作成します

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
}
于 2010-07-21T14:00:27.923 に答える
2

最も一般的なもの(この場合は文字列)を選択し、他の基準を満たしている場合は自分で内部変換を行います。

私はこれが最善の解決策ではないことを認めますが、何かが私にそれについて間違っていると思います。:-(

于 2010-07-21T13:36:34.683 に答える
2

これはばかげた答えであり、おそらくある程度は機能しますが、Javaクラスのコンストラクターが多すぎると、手間がかかりすぎる可能性がありますが、次のようになります。

他のさまざまなコンストラクターが行うすべての入力を受け取り、入力の有無に基づいて(「null」またはある種の番兵値の使用を介して)スーパークラスの適切なコンストラクターを呼び出すコンストラクターを実装するサブクラスをJavaで記述します。次に、そのJavaクラスをScalaでサブクラス化し、番兵の値をデフォルトのパラメーターとして割り当てます。

于 2010-07-21T13:59:15.213 に答える