@Vooが言うように、
あなたの質問は、すでに完全に構築されたオブジェクトで仮想メソッドを呼び出すことです。構築されたオブジェクトで仮想メソッドを呼び出すことのよく知られた失敗はよく知られていますが、ここでは当てはまりません
有効な Java 2nd Edition、項目 17: 継承のための設計と文書化、またはそれ以外の場合の禁止から:
継承を許可するためにクラスが従わなければならない制限がいくつかあります。コンストラクターは、オーバーライド可能なメソッドを直接または間接的に呼び出してはなりません。この規則に違反すると、プログラムが失敗します。スーパークラス コンストラクターはサブクラス コンストラクターの前に実行されるため、サブクラスのオーバーライド メソッドは、サブクラス コンストラクターが実行される前に呼び出されます。オーバーライドするメソッドが、サブクラス コンストラクターによって実行される初期化に依存している場合、メソッドは期待どおりに動作しません。
オブジェクトの構築中にオーバーライド可能なメソッドを呼び出すと、初期化されていないデータが使用され、実行時例外や予期しない結果が発生する可能性があります。
コンストラクターは、final または private のメソッドのみを呼び出す必要があります
からオブジェクトを作成する必要があるという問題を解決するために、静的ファクトリ メソッドを使用できますBar class
。
効果的な Java、項目 1: コンストラクターの代わりに静的ファクトリ メソッドを検討する
クライアントがクラス自体のインスタンスを取得できるようにする通常の方法は、パブリック コンストラクターを提供することです。すべてのプログラマーのツールキットに取り入れるべきテクニックがもう 1 つあります。クラスは public static factory メソッドを提供できます。これは、クラスのインスタンスを返す単なる静的メソッドです。
だから、あなたはインターフェースを持っていることに行きます:
public interface Foo {
void doFoo();
}
そして実装:
public class FooImpl implements Foo {
@Override
public void doFoo() {
//.. Do important code
}
}
ファクトリ メソッドを使用してクラスを作成するには、次の方法で作業できます。
private Foo fi
の代わりにインターフェイスを使用して、クラスの変数を定義します。private FooImpl fi
具体的な型に対してインターフェイスを使用することは、適切なカプセル化とコードの疎結合の鍵です。
デフォルトのコンストラクターをプライベートにして、クラスが外部でインスタンス化されないようにします。
private Bar() { // インスタンス化を防ぎます }
コンストラクターに存在するメソッドをオーバーライドするすべての呼び出しを削除します。
静的ファクトリ メソッドを作成する
最後に、次のBar
ようなファクトリ メソッドを持つクラスを取得します。
public class Bar {
private Foo fi;
private Bar() {// Prevents instantiation
fi = new FooImpl();
}
public static Bar createBar() {
Bar newBar = new Bar();
newBar.fi.doFoo();
return newBar;
}
}
私の上司は次のように述べています。病気を治療できるときが一番です。」!