如果有一个解决方案,如果没有使基类方法虚拟并且派生方法被标记为覆盖,那就好奇了:
我希望它跳转到派生方法,将属性设置为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);
}
}
我的猜测是因为我正在使用依赖注入接口,它正在使用基类,但我不确定原因。
答案 0 :(得分:4)
唯一的解决方案是使基础虚拟化,我认为我可以在派生中将其标记为新的并且可以工作。
没有。如果您创建一个新方法,仅代码知道编译时类型Foo2
的表达式将调用Foo2.DoSomething
。
即使TestMethod
知道foo
为Foo2
,SomeClass.DoSomething
只知道它为IFoo
,所以它只是使用IFoo
实施。 Foo2.DoSomething
不是 IFoo
的实现。
你想要多态,但你已经通过不使用虚方法有效地丢弃了它。
唯一的另一个选择是在Foo2中重新实现 IFoo
,这是谢尔盖描述的解决方案。请注意,最终会出现一些令人困惑的代码。几乎总是隐藏任何类型的方法。从根本上说,如果你想要虚拟方法的效果,你应该使用虚方法......
或者,如果使用合成而不是继承,它会更清晰:
public class MockFoo : IFoo
{
private readonly Foo foo = new Foo();
private bool doSomethingWasCalled;
public void DoSomething()
{
doSomethingWasCalled = true;
foo.DoSomething();
}
}
此委派对DoSomething
的调用,而不是试图兼顾继承层次结构。
答案 1 :(得分:1)
尝试更改Foo2
声明:
public class Foo2 : Foo, IFoo