5

C# では、クラスには何らかの処理を行って値を返す Apublic メソッドが含まれます。methodもクラス内にあり、 と同じロジックを実行し、その後にいくつかの追加処理を行ってから、値を返します。Foo()protectedBar()AFoo()

コードの重複を避けるために、戻り値をBar()呼び出しFoo()て中間値として使用します。

class A
{
  public virtual String Foo()
  {
     String computedValue;
     // Compute the value.
     return computedValue;
  }

  protected String Bar()
  {
     String computedValue;
     String intermediateValue = Foo();
     /// More processing to create computedValue from intermediateValue.
     return computedValue;
  }
}

クラスBは から継承しA、オーバーライドしますFoo()。オーバーライドは、 の基本クラスの実装を呼び出しますBar()

class B : A
{
   public override String Foo()
   {
     base.Bar();
   }
}

これは (もちろん) コンピューターがメモリ不足になるまで無限ループに入り、スタック オーバーフロー例外が発生します。

最も明白な解決策はFooInternals、Foo の内臓を含むプライベート メソッドで A を書き直すことです。Foo と Bar は、そのメソッドの結果を使用するように変更されます。

オーバーライドの代わりにAに強制的に ABar()を呼び出させる方法はありますか?Foo()

(私がここで賢すぎるのはほぼ確実です。これはポリモーフィズムに完全に反します。しかし、自分の知識をもう少し押し進めたいという衝動を抑えることはできません。)

4

1 に答える 1

7

オーバーライドの代わりに A の Bar() に A の Foo() を強制的に呼び出す方法はありますか?

直接ではありません。最も簡単なリファクタリングは、次のように変更Fooすることです。

public virtual string Foo()
{
    return FooImpl();
}

private string FooImpl()
{
    String computedValue;
    // Compute the value.
    return computedValue;
}

次に、の代わりにBarcall に変更します。FooImplFoo

(これはおそらく、「最も明白な解決策」の段落であなたが意味したことです-最初の読書で見逃しました、残念です。)

基本的に、これは継承が問題となる領域の 1 つにすぎません。ある仮想メソッドが別の仮想メソッドを呼び出す場合、サブクラスが問題を引き起こすのを回避できるように、それを文書化する必要があります。継承よりも構成を好むのは、この種のことです。もちろん、どちらも合理的な選択肢です。

于 2013-05-14T16:58:49.920 に答える