3

私がコーディングしているJavaプロジェクトでは、コンストラクターでオーバーライドされるメソッドを使用することになりました。何かのようなもの:

class SuperClass {
    SuperClass() {
        intialise();
    }

    protected void initialise() {
        //Do some stuff common to all subclasses
        methodA();
        methodB();
    }

    protected abstract void methodA();

    protected abstract void methodB();
}

class SubClass1() {
    SubClass() {
        super();
    }
    protected void methodA() { //Do something }
    protected void methodB() { //Do something }

}

class SubClass2() {
    SubClass() {
        super();
    }
    protected void methodA() { //Do something else }
    protected void methodB() { //Do something else}

}

私の場合は正常に機能しますが、現在SuperClassオブジェクトとしてのみ構築されているオブジェクトでSubClassメソッドが呼び出されるため、多少危険であることに気付きました(SuperClassを拡張する新しいクラスが追加されると見落とされる可能性があります)未来)。また、オブジェクトの作成方法が異なるため、C++では機能しません。

これを回避するために私が考えることができる唯一の方法は、初期化メソッド呼び出しを具象クラスコンストラクターに移動することです。

   class SuperClass {
    SuperClass() {            
    }

    protected void initialise() {
        methodA();
        methodB();
    }

    protected abstract void methodA();

    protected abstract void methodB();
}

class SubClass1() {
    SubClass() {
        super();
        initialise();
    }
    protected void methodA() { //Do something }
    protected void methodB() { //Do something }

}...

これは、この問題を克服するための一般的な方法ですか?SuperClassを拡張する他のすべてのクラスがinitialise()を呼び出すことを覚えておく必要があるのは、残念なことです(そして忘れがちです)。

また、コンストラクターでFactoryメソッドを使用する、より複雑な状況で同様のことを行っていることに気付きました。これは、サブクラスでオーバーライドされて、実装する具象クラスを決定します。これを回避してデザインパターンをそのまま維持するために私が考えることができる他の唯一の方法は、おそらく2段階のプロセスで構築することです。つまり、最小限で構築し、2番目のメソッドを呼び出してジョブを終了します。

4

4 に答える 4

1

これと同じくらい複雑な初期化が必要なオブジェクトは、実際にはファクトリメソッドを使用して作成する必要があります。あなたはファクトリーについて言及していますが、コンストラクターから呼び出されているので、それも単純なアプローチのようには聞こえません。基本クラスにファクトリ、公開されていないコンストラクタ、および返す具象クラスを決定するメカニズムがある場合、そのファクトリは初期化ポリシーを簡単に適用します。

于 2012-07-20T20:48:24.740 に答える
0

Bruce Eckel が彼の「Thinking in Java」で示唆しているのは、クラス SuperClass の methodA() とメソッド B() を final または private (暗黙的に final) にすることです。これにより、スーパークラス コンストラクターからアクセスできるようになりますが、派生クラスにはありません。これらのメソッドにアクセスするため、危険なオーバーライドはできません。派生クラスで宣言された同様のシグネチャを持つメソッドは、単に新しいメソッドになります。

于 2016-07-03T19:39:02.677 に答える
0

サブクラスの methodA() と methodB() が呼び出されたときにサブクラスが適切に構築されないため、これは本当に良い考えではありません。これは、クラスを拡張する人々にとって非常に混乱するでしょう。init()dlev のコメントで提案されているように、代わりに要約を使用することをお勧めします。

于 2012-07-20T19:22:17.077 に答える
0

必要以上に物事を複雑にしているのだろうか。

あなたの例では、 methodA の各実装によって行われたものは、実装を行うクラスのコンストラクターに移動できます。したがって、SubClass::methodA を使用する代わりに、ロジックを SubClass コンストラクターに移動するだけです。

これを行うと、さまざまな初期化ビットが実行される順序を制御するのが難しくなる可能性がありますが、明確になります。

于 2012-07-20T19:28:19.157 に答える