作者:林子云
链接:https://www.zhihu.com/question/36909455/answer/298159409
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一 接口与抽象类的语法上区别

1.1)接口都是抽象方法,而抽象类中既可以有抽象方法,也可以有(实例)instance 方法。

1.2)接口中的变量都是 public static final 而抽象类中的变量可以被任何通用修饰符修饰。

1.3)一个类可以实现多个接口,但是只能继承一个抽象类。

  • 抽象类继承接口,可实现也可不实现接口中定义的方法
    • 如果抽象类中实现了 → 抽象类的子类可不用实现,但需要实现抽象类中定义的接口(如果有的话),也可重写覆盖抽象类的方法
    • 如果抽象类中没有实现,则子类需要实现接口

二 接口与抽象类的涵义上区别

2.1)接口定义的是所有实现类必须实现的规则,是一种承诺和约束,保证所有的实现类都有相关的方法可供调用;

抽象类更多的是对通用的、基础的方法封装,让子类复用,避免在子类开发重复的代码。子类只需实现抽象方法,也可以有选择的覆盖抽象父类的方法。

三 实践

3.1)将依赖的、通用的对象放到Abstract的基类中,减少重复代码。

例如各种数据库 manager,service,logger 等,并设置成 protect 级别。

3.2)将通用工具代码、业务代码放到基类中可供不同子类调用。

比如,parseData(),getLong(),str2Long() 之类的。

3.3)制定类的处理流程,封装通用功能代码,让子类按照某种流程来处理。

比如,基类中定义一个 abstract 的 subExecute(),在基类中,可以先检查入参,查询相关数据,做一些其他业务事情,然后执行subExecute()。在外面统一处理异常。

3.4)场景举例demo。商家要管理活动,可以创建和修改活动数据,由不同的类来完成。

  1. public interface ActivityManager {
  2. public Result process(Param param)
  3. }
  4. public abstract class BaseActivityManager implement ActivityManager {
  5. // 定义成 protect,子类可以访问到
  6. protect Logger logger = xxxLogger;
  7. @Autowired
  8. protected UserManager userManager;
  9. @Autowired
  10. protected ItemManager itemManager;
  11. public abstract Result subProcess(Param param);
  12. //定义子类处理流程
  13. public Result process(Param param) {
  14. try{
  15. //入参检查
  16. checkParam(param);
  17. //用户登录检查
  18. checkLogin(param);
  19. //活动权限检查,商家是否能管理该活动
  20. checkRole(param)
  21. //操作日志记录
  22. operationLog(param);
  23. //其他业务逻辑
  24. doOtherBiz(param);
  25. //最后执行操作
  26. return subProcess(Param param);
  27. }catch() {
  28. //记录异常
  29. log(e)
  30. }
  31. }
  32. }
  33. public class AddActivityManager extends BaseActivityManager {
  34. Result subProcess(Param param) {
  35. //todo
  36. }
  37. }
  38. public class EditActivityManager extends BaseActivityManager {
  39. Result subProcess(Param param) {
  40. //todo
  41. }
  42. }

当也可以在抽象类中不实现接口定义的方法,只是提供一些公共方法的封装,子类继承抽象类,去实现接口的时候,调用 super.xxx 方法(即抽象类中封装的方法)。