空抽象类是不好的做法,为什么?

Ant*_*val 10 java refactoring abstract-class

我们的代码库中有几个空的抽象类.我觉得很难看.但除了这个非常愚蠢的理由(丑陋)之外,我应该重构它(例如空的界面)吗?

否则,代码是健壮的并经过充分测试.因此,如果它只是出于"审美"的原因,我将通过并让空的抽象类保持不变.

你怎么看?

编辑:

1)通过"空抽象类",我的意思是:

public abstract class EmptyAbstractClass {}
Run Code Online (Sandbox Code Playgroud)

2)"空虚"的原因:Hibernate.我根本没有掌握这个持久性框架.我只是理解一个接口不能映射到一个表,并且由于这个技术原因,一个类比接口更受欢迎.

Vin*_*nie 18

在这种情况下,接口更可取,因为它使您的代码更易于维护.也就是说,您只能扩展单个类,但可以实现许多接口.

如果现在绝对没有直接影响,我就不会碰它.如果维护事件出现需要你进行更改,那么我会重构它,因为我已经在代码中了.

换句话说,如果没有破坏,请不要修理它.


Dav*_*ler 7

要问的问题是:"我想用这些代码做什么,我不能做,或者很难做到,因为这些空的抽象类在那里?" 如果答案是"什么都没有",你应该让他们独自一人.如果答案是"某事",删除它们可能是值得的 - 但如果可以的话,请先与创建它们的人交谈,以确保它们没有一些微妙的目的.例如,也许您的代码使用反射来查找特定ABC的所有实例并对它们执行特殊操作,在这种情况下,您的重构可能会以微妙的方式破坏代码.


ext*_*eon 6

它不一定比替代品更难看,它可能重复代码.

在理想的世界中,您将能够仅使用接口进行建模.例如:Vehicel - > Car - > Pontiac.

但是对于所有车辆可能存在相同的逻辑,因此接口不合适.而且你没有特定于汽车的逻辑.但是你确实需要Car抽象,因为您的TrafficLightController想要区分汽车和自行车.

在这种情况下,你需要制作和抽象汽车.

或者你可以创建一个界面Vehicle,一个VehicleImpl实现Vehicle,一个接口Car extends Vehicle,一个接口Pontiac实现Car,一个PontiacImpl实现Pontiac扩展VehicleImpl.我个人不喜欢并行的接口层次结构,以防止空抽象类多于空抽象类.

所以我想这是一个品味问题.

一个警告; 如果你使用像Spring这样的许多代理类和一些测试框架,并行接口层次结构可能会导致意外错误减少.

  • +1:我之前没有考虑的有趣情况. (2认同)

Pas*_*ent 5

空的抽象类对我来说没有任何意义,抽象类应该用于继承某些行为。所以,我倾向于同意,这是一个相当丑陋的设计,并且对抽象类的使用非常糟糕,应该首选标记接口。所以你有两个选择:

  1. 等到您需要扩展另一个类来满足真正的需要,并且对抽象类感到恼火时,才用接口替换它。
  2. 不要等待并修复设计。

在这种特殊情况下,确实,目前的实际设计并没有真正造成伤害,因此您可以接受它。然而,我认为替换这些抽象类是一个非常简单的重构(使它们成为接口并替换extendsimplements出现编译错误的地方),而且我真的看不出什么会被破坏,所以我会这样做。

就我个人而言,人们当然可能不同意,我不喜欢过于防守。有了像“如果它没有坏,就不要修复它”这样的规则,你将永远不会重构任何东西(“我的测试通过了,为什么我应该重构?”)。冻结代码绝对不是正确的解决方案,积极测试才是正确的解决方案


Mic*_*urd 5

听起来像这样是创建一个对象层次结构的结果,最终没有任何常见的功能在它的最顶层.我怀疑直接的子类本身是抽象的,或者至少有自己的子类.另一种可能性是你的代码中散布着大量的函数实例.

空的最高级别本身并不是一个大问题,但我会检查以确认实际上不存在共同的功能.假设它确实存在,我会考虑在父类中提取常用功能.我肯定会留意一下,并认真考虑重构它(例如,参考Refactoring to Patterns(Kerievsky)).