これに似たトピックがいくつかありますが、十分な答えのあるトピックは見つかりませんでした。
Javaでのコンストラクタのオーバーロードのベストプラクティスを知りたいと思います。私はすでにこのテーマについて自分の考えを持っていますが、もっとアドバイスを聞きたいです。
単純なクラスでのコンストラクターのオーバーロードと、既にオーバーロードされたクラスの継承中のコンストラクターのオーバーロードの両方を参照しています(つまり、基本クラスにはコンストラクターがオーバーロードされています)。
ありがとう:)
「公式ガイドライン」はありませんが、KISSおよびDRYの原則に従います。オーバーロードされたコンストラクターをできるだけシンプルにします。最も簡単な方法は、this(...)のみを呼び出すことです。そうすれば、パラメーターを一度だけ確認して処理するだけで済みます。
public class Simple {
public Simple() {
this(null);
}
public Simple(Resource r) {
this(r, null);
}
public Simple(Resource r1, Resource r2) {
// Guard statements, initialize resources or throw exceptions if
// the resources are wrong
if (r1 == null) {
r1 = new Resource();
}
if (r2 == null) {
r2 = new Resource();
}
// do whatever with resources
}
}
単体テストの観点からは、リソースをクラスに入れることができるため、クラスのテストが簡単になります。クラスに多くのリソースがある(または一部のOOオタクがそれを呼ぶように協力者)場合は、次の2つのことのいずれかを検討してください。
public class SimpleParams {
Resource r1;
Resource r2;
// Imagine there are setters and getters here but I'm too lazy
// to write it out. you can make it the parameter class
// "immutable" if you don't have setters and only set the
// resources through the SimpleParams constructor
}
Simpleのコンストラクターは、SimpleParams
パラメーターのみを分割する必要があります。
public Simple(SimpleParams params) {
this(params.getR1(), params.getR2());
}
…またはSimpleParams
を属性にします。
public Simple(Resource r1, Resource r2) {
this(new SimpleParams(r1, r2));
}
public Simple(SimpleParams params) {
this.params = params;
}
リソースを初期化するファクトリクラスを作成します。これは、リソースの初期化が少し難しい場合に便利です。
public interface ResourceFactory {
public Resource createR1();
public Resource createR2();
}
その後、コンストラクターは、パラメータークラスと同じ方法で実行されます。
public Simple(ResourceFactory factory) {
this(factory.createR1(), factory.createR2());
}
ええ...あなたがその時にあなたにとってより簡単なものに応じて、両方の方法を組み合わせてマッチさせることができます。パラメータクラスと単純なファクトリクラスは、同じ方法で使用されるSimple
クラスを考慮すると、ほとんど同じものです。
ベストプラクティスは、関連パラメータのデフォルトでthis()
を呼び出すことでオーバーロードされたコンストラクターが参照する単一のプライマリコンストラクターを持つことだと思います。この理由は、オブジェクトの構築された状態が何であるかをより明確にするためです-実際には、プライマリコンストラクターを実際のコンストラクターのみ、他のコンストラクターはそれに委任するだけです
この一例はJTable
かもしれません-プライマリコンストラクターはTableModel
(および列と選択モデル)を取り、他のコンストラクターはこのプライマリコンストラクターを呼び出します。
スーパークラスに既にオーバーロードされたコンストラクターがあるサブクラスの場合、親クラスのコンストラクターをprimaryそして、単一のプライマリコンストラクタを持たないことは完全に合法だと思います。たとえば、Exception
を拡張するとき、3つのコンストラクターを提供することがよくあります。1つはString
メッセージを受け取り、1つはThrowable
の原因を取り、もう1つは両方を受け取ります。これらの各コンストラクターは、super
を直接呼び出します。
いくつかの組み合わせのみが有効な多くのオプションを持つ非常に複雑なクラスがある場合は、Builderの使用を検討してください。コード的にも論理的にも非常にうまく機能します。
Builderは、フィールドを設定するためだけに設計されたメソッドを持つネストされたクラスであり、ComplexClassコンストラクターは引数としてそのようなBuilderのみを取ります。
編集:ComplexClassコンストラクターは、Builderの状態が有効であることを確認できます。 ComplexClassでセッターを使用するだけの場合、これは非常に困難です。
すべてのクラスが同じように作成されるわけではないため、クラスの種類に本当に依存します。
一般的なガイドラインとして、2つのオプションを提案します。
さて、ここにオーバーロードされたコンストラクタの例を示します。
public class Employee
{
private String name;
private int age;
public Employee()
{
System.out.println("We are inside Employee() constructor");
}
public Employee(String name)
{
System.out.println("We are inside Employee(String name) constructor");
this.name = name;
}
public Employee(String name, int age)
{
System.out.println("We are inside Employee(String name, int age) constructor");
this.name = name;
this.age = age;
}
public Employee(int age)
{
System.out.println("We are inside Employee(int age) constructor");
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
}
上記の例では、オーバーロードされたコンストラクターを見ることができます。コンストラクターの名前は同じですが、各コンストラクターには異なるパラメーターがあります。
Javaでのコンストラクタのオーバーロードにさらに光を当てるリソースをいくつか紹介します。
コンストラクター 。