web-dev-qa-db-ja.com

Scalaで、Javaクラスを複数のコンストラクターでサブクラス化するにはどうすればよいですか?

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

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

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

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

59
Seth Tisue

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

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
}

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

89
Seth Tisue

[〜#〜] 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
}
5
oxbow_lakes

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

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

2
JAB

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

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

2
corsiKa