是的,这显然很糟糕;这是因为您的类型层次结构必然是公共 API。如果您的 API 公开了 UserManagementService,我可以将其用作 DatabaseConnectionService 对象。这意味着您选择让 UMS 扩展 DCS 被锁定 - 如果您更改它,任何使用您的 UMS 的代码都可能会失败。您可以尝试在文档中解决此问题:
/**
* Lets you query information about, and perform operations on,
* the storage of users allowed on this service.
*
* IMPORTANT NOTE: Even though this class extends DatabaseConnectionService,
* this is <em>not guaranteed</em> by this implementation,
* so do not rely on this!
*/
public class UserManagementService extends DatabaseConnectionService {
...
}
但您肯定会看到这是非常次优且“丑陋”的(难以维护 - 您无法测试您无法控制的其他代码实际上是否注意到您的警告)。
反过来也适用:如果 DCS 添加了一些对 UMS 来说毫无意义的东西,那么你的 UMS 突然间就坏掉了,并暴露了一些毫无意义的疯狂东西,并导致许多问题或更糟.
与声明学生是某种人相比:这本质上是正确的;这不仅仅是一个方便的实现细节。如果整个国家都获得了某种 servicenumber 功能,而您扩展 Person 类来支持它,那么学生们一下子也获得了这个 servicenumber 的东西。但这很好:毕竟,学生是个人。
那么,你如何解决它?
简单。不要扩展 DCS。创建一个DCS类型的字段,如果DCS有一堆方法你想让UMS也有,把它们写出来。他们的实现可以是非常简单的oneliners:
public int count() {
return dataConService.count();
}
// and a lot more of this, if really needed.
对此逻辑的常见反驳:但我控制着这一切,而且我预计不会添加新功能!
好吧,好吧,但要明白,单人一次性项目是谈论“风格指南和代码清洁度”的一个非常糟糕的基础 - 只是你,周末闲逛,随心所欲地写,你会很好。
当一个由 50 名程序员组成的团队编写一个应用程序时,风格指南和编码方法变得非常有用,该应用程序将在业务中生存和发展十多年,程序员离开,新程序员加入团队,项目结束后 5 年已经启动,您甚至还没有想到的功能,因为客户的需求需要添加。
考虑到这一点,请理解代码库变得庞大,并且很难安全地更改内容并培训新程序员熟悉它。使这变得更容易的一种非常有用的方法是积极地模块化事物:任何时候您都可以在白板上绘制整个源代码库(这将是巨大的),然后在它的一小部分周围画一个小圆圈然后去:这个东西可以自己理解,自己测试,并在不完全理解所有其他源代码的情况下开发 - 这好。这就是你想要的。
“UMS 当前扩展了 DCS,但不依赖它”正是使绘制那个小圆圈更加复杂的事情,这就是为什么这样做不是一个好主意。