0

基本クラスのメソッドを仮想化し、派生メソッドにオーバーライドのマークを付けずに、これに対する解決策があるかどうかだけ知りたいです。

派生メソッドにジャンプして、プロパティをtrueに設定したいのですが(テスト目的で、これはモックのようです)、基本クラスにジャンプしています。唯一の解決策は、ベースを仮想化することです。派生したもので新しいものとしてマークを付けることができ、それでうまくいくと思いました。

   public class SomeClass
   {
      private readonly IFoo _foo;

      public SomeClass(IFoo foo)
      {
         _foo = foo;
      }

      public void DoSomething()
      {
         _foo.DoFoo();
      }
   }

   public interface IFoo
   {
      void DoFoo();
   }

   public class Foo : IFoo
   {
      public void DoFoo()
      {

      }
   }

   public class Foo2 : Foo
   {
      public bool DoFooWasCalled { get; set; }

      public new void DoFoo()
      {
         DoFooWasCalled = true;
         base.DoFoo();
      }
   }

失敗しているテストは次のとおりです。

   [TestFixture]
   public class TestingCSInheritance
   {
      [Test]
      public void TestMethod()
      {
         var foo = new Foo2();
         var someClass = new SomeClass(foo);
         someClass.DoSomething();
         foo.DoFooWasCalled.ShouldBe(true);
      }
   }

私の推測では、インターフェイスで依存性注入を使用しているため、基本クラスを使用していますが、その理由はわかりません。

4

2 に答える 2

4

唯一の解決策は、ベースを仮想化することです。派生したもので新しいものとしてマークを付けることができ、それでうまくいくと思いました。

いいえ。新しいメソッドを作成する場合は、コンパイル時の型がの式を認識しているコードのみFoo2がを呼び出しますFoo2.DoSomething

TestMethodとして知っていても、としてfooしか知らないので、実装を使用しているだけです。の実装ではありませんFoo2SomeClass.DoSomethingIFooIFooFoo2.DoSomethingIFoo

ポリモーフィズムが必要ですが、仮想メソッドを使用しないことで事実上破棄しています。

他の唯一のオプションは、Foo2で再実装することです。これは、Sergeyによって説明されたソリューションです IFooこれはかなり紛らわしいコードで終わることに注意してください。ほとんどの場合、メソッドの非表示はどのようなものでもかまいません。基本的に、仮想メソッドの効果が必要な場合は、仮想メソッドを使用する必要があります...

または、継承の代わりにコンポジションを使用した方がクリーンです。

public class MockFoo : IFoo
{
    private readonly Foo foo = new Foo();
    private bool doSomethingWasCalled;

    public void DoSomething()
    {
        doSomethingWasCalled = true;
        foo.DoSomething();
    }
}

これにより、継承階層を調整しようとする代わりに、への呼び出しが委任されます。DoSomething

于 2012-07-22T19:37:11.693 に答える
1

Foo2次のように宣言を変更してみてください。

public class Foo2 : Foo, IFoo
于 2012-07-22T19:33:00.540 に答える