namespace NUnitTestAbstract
{
public abstract class BaseTestClass1
{
public abstract void BaseTestClass1Method();
}
public abstract class BaseTestClass2 : BaseTestClass1
{
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodA() { }
public void SomeTestMethodB() { }
}
public abstract class BaseTestClass3 : BaseTestClass1
{
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodX() { }
public void SomeTestMethodY() { }
}
public class TestClass2A : BaseTestClass2
{
public override void BaseTestClass1Method()
{
// do stuff
}
}
public class TestClass2B : BaseTestClass2
{
public override void BaseTestClass1Method()
{
// do same stuff as TestClassA
}
}
public class TestClass3A : BaseTestClass3
{
public override void BaseTestClass1Method()
{
// do stuff
}
}
public class TestClass3B : BaseTestClass3
{
public override void BaseTestClass1Method()
{
// do same stuff as TestClass3A
}
}
}
此刻我有上述结构。扩展另一个基类的基类。基类由两个子类扩展。 BaseTestClass1Method
的实现对于两个子类是相同的。如果可以从两个父母那里扩展,我会创建一个扩展BaseTestClass1
实施BaseTestClass1Method
的课程。然后,这两个子类将扩展BaseTestClass2
和新类,这样我只需要实现BaseTestClass1Method
一次
当我从BaseTestClass1添加另一个BaseTestClass3(与BaseTestClass2相同的级别)并从中创建子类时,我有更多的重复代码来实现BasetestClass1Method。
如何用正确的模式解决这个问题?
这是一个更实施的例子:
namespace NUnitTestAbstract
{
public interface IServer { }
public abstract class ServerBase
{
public abstract IServer GetServerInstance();
}
public abstract class SomeTests1Base : ServerBase
{
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodA() { }
public void SomeTestMethodB() { }
}
public abstract class SomeTests2Base : ServerBase
{
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodX() { }
public void SomeTestMethodY() { }
}
public class TestClass2A : SomeTests1Base
{
public override IServer GetServerInstance()
{
IServer serverX = null;
return serverX;
}
}
public class TestClass2B : SomeTests1Base
{
public override IServer GetServerInstance()
{
IServer serverX = null;
return serverX;
}
}
public class TestClass3A : SomeTests2Base
{
public override IServer GetServerInstance()
{
IServer serverY = null;
return serverY;
}
}
public class TestClass3B : SomeTests2Base
{
public override IServer GetServerInstance()
{
IServer serverY = null;
return serverY;
}
}
}
答案 0 :(得分:6)
。调用父方法时类型D
的实例 - 它如何知道哪个父类?
而不是具有许多抽象类的深度继承树使用接口和组合。
使用某个接口定义逻辑,并为该特定逻辑使用不同的具体类型。然后像TestClassb
这样的类可以创建所需逻辑的实例,或者更好地依赖于它的构造函数:
public class Derived
{
public Derived(ILogic someDependentLogic) { }
}
在您的代码评论中,您说TestClass2B
它与TestClassA
具有相同的行为,但它来自BaseTestClass2
。您应该正确考虑继承树。 TestClass2B
应该是BaseTestClass2
的类型吗?或者它应该是TestClassA
的类型?
如果它实际上是一种"那种" TestClassA
然后继承它。
所有答案都是针对特定领域的,但我建议您阅读有关作文的内容:它将帮助您了解您的关系类型以及适合您情况的正确设计。
此外,还有一些好的设计模式可供查看,例如dofactory下的State
,Strategry
,Decorator
在看到Composition
的优势以及何时使用它之后,您可以查看SOLID
和Inversion Of Control
它将有助于它们完美地融合在一起。
答案 1 :(得分:2)
使用接口而不是抽象类。您可以从多个接口继承,但只能从一个类继承。
答案 2 :(得分:2)
我不明白你为什么不在BaseTestClass2中重写BaseTestClass1Method
public abstract class BaseTestClass2 : BaseTestClass1
{
public override void BaseTestClass1Method()
{
// do same stuff as TestClassA
}
}
要实现这样的目标,您可以使用不同的模式,例如
答案 3 :(得分:2)
您可以在BaseTestClass2中实现BaseTestClass1Method,以便TestClassA和TestClassB获得相同的实现。但是,根据您的要求,走这条路可能会以继承地狱结束。
您可以通过其构造函数(依赖注入(DI))将实现BaseTestClass1的实例传递到BaseTestClass2,而不是从BaseTestClass1继承BaseTestClass2。然后在TestClassA和TestClassB中简单地调用实例中注入的BaseTestClass1Method方法。这会将继承级别降低到1。
使用诸如Autofac或Unity之类的DI容器将BaseTestClass1的正确实现注入BaseTestClass2的后代。
<强>更新强>
从你的例子开始
namespace NUnitTestAbstract
{
public interface IServer { }
public class BaseServer()
{
private IServer _server;
public BaseServer(IServer server)
{
_server = server;
}
public IServer GetServerInstance()
{
return _server;
}
}
public class SomeTests1 : ServerBase
{
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodA() { }
public void SomeTestMethodB() { }
}
public class SomeTests2 : ServerBase
{
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodX() { }
public void SomeTestMethodY() { }
}
}
public class ServerA : IServer
{
//Implementation
}
public class ServerB : IServer
{
//Implementation
}
var someTests1 = new SomeTests1(new ServerA()); var someTests2 = new SomeTests2(new ServerB());
请注意,我已删除抽象类并将服务器实现注入新实例。
我放弃了TestClass(1..n),因为我看不出对它们的需求,但只有你能知道答案。
此外,我已经动态编写了这段代码,所以它还没有经过测试,也没有检查它是否可以编译,但你应该能够得到它的要点。希望它有所帮助。
答案 4 :(得分:1)
按照他人的建议使用界面:
namespace NUnitTestAbstract
{
public interface IBaseTes1
{
void BaseTestClass1Method();
}
public abstract class BaseTestClass2 : IBaseTes1
{
void IBaseTes1.BaseTestClass1Method()
{
}
// not overriding BaseTestClass1Method, child classes should do
public void SomeTestMethodA() { }
public void SomeTestMethodB() { }
}
public class TestClassA : BaseTestClass2
{
}
public class TestClassb : BaseTestClass2
{
}
}