面向对象 - 在何处放置此接口声明

时间:2009-08-07 06:26:05

标签: oop interface abstract-class

我有一些问题,包括接口和抽象基类的OO设计。请考虑以下情形:

我有一个抽象的低音类“DataObjectBase”和一个派生类“UserDataObject”。我还有一个“IDataObject”接口。接口当然会公开我的Data Objects必须公开的所有公共方法和属性,你可能会猜测抽象基础实现了所有数据对象共有的方法和属性。

我的问题是,如果抽象的bass类DataObjectBase实现了接口IDataObject中指定的所有内容,是应该在基类还是派生类上声明接口?

在基类上声明的C#接口是非常适用于派生类,但这是最佳实践吗?在我看来,在基类上实现接口使派生类实现接口变得不那么明显,但是再次要求为每个派生类指定接口。

此外,如果基类不是抽象的,那么推荐会改变吗?

第二个子问题:如果基类实现了IDataObject接口的所有方法/属性,那么接口是否还需要?可以简单地使用基类typename代替接口名称,即:

私有DataObjectBase _dataObject;
私有IDataObject _dataObject;

在上面的例子中(同样,base实现了接口公开的所有内容),两者都可以分配相同的派生类型。我个人总是在这些情况下使用界面,但我很想听听人们的想法。

提前致谢。

3 个答案:

答案 0 :(得分:1)

如果您的用户类始终从一个基类继承,那么您不需要该接口。如果有可能您将拥有与接口匹配但不是从基类派生的类,则使用该接口。

对于隐藏在基类中的接口,因此在用户类中不能立即显示,这是正常的,可以由编译器处理。这也是良好命名约定的用武之地 - 您的UserDataObject具有与IDataObject匹配的名称,DataObjectBase也是如此。您可以在类文件中添加一条注释,表明它继承自IDataObject,但它可以看到它继承自DataObjectBase,而DataObjectBase看起来就像是从IDataObject继承了它的名称。

答案 1 :(得分:1)

我对这些问题的思考方式是考虑不同的人阅读代码,如果你愿意,可以考虑“角色”。还要考虑系统的整体可维护性。

首先有一些代码期望使用接口。它是根据界面编写的,作者对(应该)没有兴趣实现。这就是我们提供Interface类的原因。从这个角度来看,抽象基类只是众多可能的实现层次结构中的一个。不要告诉这个角色有关实现细节。保持界面。

然后我们有了设计实现的角色。他们提出了一种可能的方法并发现了一些变化,因此他们希望将共同的代码拉到一起。摘要基类 - 填写常用的东西,让详细的实施者填补空白。通过提供“您的代码在这里”的抽象方法来帮助他们。请注意,这些方法不仅需要接口中的方法。另请注意,此抽象基类甚至可以实现更多的一个接口! (例如,它是CleverThingWorker,但也是IntermediateWorkPersister。)

然后我们有了实际执行精细详细实现的角色。填补这里的空白。死得易懂。在这种情况下,您甚至不需要考虑接口。你的工作就是把这个抽象的课程变得具体。

底线...我使用Interfaces和Base类。您将接口放在基类上。我们不会通过将其添加到实现类来增加价值。

答案 2 :(得分:0)

需要提及的另一件事是,使用接口可以更容易地实现自动化测试。

例如,假设接口的某个方法应该抛出异常 - 例如'DatabaseConnectionLostException' - 并且您希望测试客户端代码以检查它在这种情况下是否正常运行。

提供抛出异常的接口实现是一件简单的事情,允许编写测试。

如果您使用抽象基类而不是接口,则此操作会相当棘手(好吧,您可以使用Mocks,但界面解决方案更清晰)