Java继承还是静态方法

Java继承还是静态方法,java,inheritance,static,Java,Inheritance,Static,有一个名为AbstractAgent的抽象类,目前有27个类在扩展这个类 我已经开始开发一些代理,我的5个代理都在扩展AbstractAgent类 现在,我观察到在我的所有5个代理中都有一个getFilePath()。然后我意识到,在现有的27个类中,也有很多类使用了这种方法。我认为把这个方法放在基类AbstractAgent中,让每个人都使用这个方法是个好主意。但是我不希望所有现有的类都更改它们的代码,我已经更改了方法名,这样以后任何人都可以使用它 做代码审查的人建议我不要碰AbstractA

有一个名为
AbstractAgent
的抽象类,目前有27个类在扩展这个类

我已经开始开发一些代理,我的5个代理都在扩展
AbstractAgent

现在,我观察到在我的所有5个代理中都有一个
getFilePath()
。然后我意识到,在现有的27个类中,也有很多类使用了这种方法。我认为把这个方法放在基类
AbstractAgent
中,让每个人都使用这个方法是个好主意。但是我不希望所有现有的类都更改它们的代码,我已经更改了方法名,这样以后任何人都可以使用它

做代码审查的人建议我不要碰
AbstractAgent
类,因为它已经被现有客户机使用,并且把这个方法放在一些实用类中


我不相信他的论点。任何人都想表达自己的想法。

向父类添加公共逻辑是抽象类的一个强大方面,这种添加是向前兼容的更改。当然,除非您不知道这个类的某些用法,并且您新添加的方法具有相同的名称。但即使这样,如果子类覆盖了这样的方法,它自己的方法也会被调用,因此它仍然是一个向前兼容的更改。

在这种情况下,因为
AbstractAgent
类已经被其他类使用,正如您所提到的不是所有类都实现了这个方法,那么您确实不应该更改
AbstractAgent
。但是,您可以在另一个名为say
AbstractAgentWithFilePath
的抽象子类中扩展
AbstractAgent
,该子类声明您需要的附加方法,然后让这些类扩展
AbstractAgentWithFilePath
类,将它放在抽象中是一个很好的选择,但如果不是,则将它放在另一个处理所有文件相关操作的实用程序类中是可以接受的。

如果
getFilePath()
方法对于所有
AbstractAgent
的子类都完全相同,则无论如何都可以将它拉到抽象类中(使用IDE的重构工具),将其从子类中删除,然后运行单元测试(您确实有单元测试,对吗?),并检查是否一切正常

如果
getFilePath()
的某些实现之间存在差异,但大多数实现是相同的,那么最好将最常见的实现拉到抽象类上,从使用它的子类中删除它,并在实现不同的情况下重写子类中的方法

现在,如果方法的不同实现之间存在太多的差异,请保持代码库不变


在实用程序类中定义静态方法(例如,
FileUtil
)只有当该方法与代理类的功能没有直接关系,或者该方法可以用于对象层次结构的其他部分,而与代理没有直接关系时,才有意义。

这里没有正确的答案。只有您、您的同事和您的公司知道AbstractAgent的使用方式和位置,以及如何更改它影响不同的团队、部门或客户。关于代码定位的决策通常更具政治性和社会性,而不是由“洁净室”设计选择驱动

从纯代码的角度来看,我支持彻底的重构:去掉AbstractAgent所有子类中的所有重复代码,并将所有人移动到AbstractAgent中的新getFilePath()

但是,您可能没有权限这样做,并且可能会遭到拒绝。或者getFilePath()有时会略有不同(您对此并不清楚)。在这种情况下,您所做的任何选择都似乎是一种妥协。您的代码审阅者可能会对“getFilePath2()”提出反对意见在AbstractAgent中,因为它揭示了不完善的代码重用问题,并感觉到它正在“污染”超类,因为它提供了一个临时解决方案,让每个人都了解超类中真正通用的共享代码,从而真正解决了这个问题。谁知道呢


在完全重构完成之前,也许静态实用程序方法是一个更好的选择。

imho,这是一个糟糕的论点,我支持重构。这是一个很好的解决方案,但仅仅为一个方法创建一个多类层次结构对我来说没有意义。AbstractAgent是一种标准的东西,每个人都会扩展这个cl要求他们使用AbstractAgentWithFilePath有点困难。但从逻辑上说,你是对的。我喜欢这样,只是我认为他可能会因为在层次结构中引入一个新类而受到批评,因为这个类完全基于一个可能微不足道的实用方法。哦,好吧。有道理。这符合我的想法。一般来说不是真的。重载解决方案很容易成为问题并破坏兼容性。“很抱歉,我们添加了一个函数,现在您的代码调用了错误的函数”是一种与库的客户端交朋友的好方法。这种思路是+1。添加重载方法不应破坏向后兼容性。最坏的情况是,您给它起了不同的名称,然后它肯定不会破坏向后兼容性。@Perception它肯定会破坏向后兼容性,没有办法您可以保证某个函数名不会被某个任意外部子类使用。@Voo-hmmmm,请详细说明添加新方法如何打破与现有代码的向后兼容性,具体取决于所描述的用户情况。getFilePath()方法功能在所有类中都是相同的