2009-08-07 25 views
1

我有几个问题需要明智的人员参与面向对象设计的接口和抽象基类。考虑以下情况:面向对象 - 何处放置此接口声明

我有一个抽象低音类“DataObjectBase”和派生类“UserDataObject”。我也有一个接口“IDataObject”。当然接口暴露了我的数据对象必须公开的所有公共方法和属性,并且您可能猜测抽象基础实现了所有数据对象通用的方法和属性。

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

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

此外,如果基类不是抽象的,那么这个建议是否会改变?

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

private DataObjectBase _dataObject;
private IDataObject _dataObject;

在上面的示例中(基地再次实现接口公开的所有内容)都可以分配相同的派生类型。就我个人而言,我总是在这些情况下使用界面,但我对于听取人们的想法感兴趣。

在此先感谢。

回答

1

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

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

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

然后我们有实际做好细节实现的角色。填补这里的空白。死容易理解。在这种情况下,你甚至不需要考虑接口。你的工作是使抽象类具体化。

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

1

如果您的用户类别为总是从一个基类继承,那么您不需要该接口。如果有可能会有与接口相匹配但不是从基类派生的类,请使用该接口。

至于隐藏在基类中的接口,因此不能立即在用户类中看到,这是正常的,可以由编译器处理。这也是良好的命名约定所在 - 您的UserDataObject具有与IDataObject相匹配的名称,就像DataObjectBase一样。您可以向类文件添加一条评论,说它从IDataObject继承,但它将可见,它从DataObjectBase继承,而DataObjectBase继而看起来像它通过名称继承IDataObject。

0

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

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

提供引发异常的接口的实现是一件简单的事情,允许写入测试。

如果你使用抽象基类而不是接口,这个操作会比较棘手(确定,你可以使用Mocks,但接口解决方案更简洁)