一个类继承一个接口的实现类、两个类实现同一个接口、两个类同时继承一个实现了某一接口的抽象类。三者的区别是什么呢
-
架构对比图
类继承接口的实现类
[接口] ↑ [实现类] ↑ [子类]
子类通过继承获得接口的实现,可以选择性重写方法。
两个类实现同一个接口
[接口] ↑ ↑ [类A] [类B]
每个类独立实现接口,提供自己的行为实现。
继承实现接口的抽象类
[接口] ↑ [抽象类] ↑ ↑ [类A] [类B]
抽象类提供部分实现,子类完成特定功能的实现。
1. 两个类实现同一个接口
2. 一个类继承接口的实现类
3. 两个类继承实现了接口的抽象类
2. 代码复用与继承层次
模式 代码复用机制 继承层次特点 风险与限制 继承接口的实现类 通过继承父类B复用其逻辑(包括接口I的实现) 形成“接口→父类→子类”的纵向继承链 父类B的修改可能影响子类A;若子类重写方法可能导致“行为不一致” 两个类实现同一接口 无直接代码复用,各实现类独立实现接口方法 平行结构,无继承关联 重复代码风险高,但灵活性更强 继承实现接口的抽象类 通过抽象类复用公共逻辑(如模板方法),子类专注差异化实现 抽象类作为基类,子类继承其实现 抽象类的修改会影响所有子类;若抽象类未完全实现接口,子类需补全 3. 多态性与类型系统
模式 多态性表现 类型关系 接口契约履行 继承接口的实现类 子类A的实例可向上转型为接口I,同时保留父类B的特性 类A是类B的子类,类B是接口I的实现类 通过父类B履行接口契约 两个类实现同一接口 类C和类D的实例均可视为接口I的类型,具体行为由各自实现决定 接口I是抽象契约,类C和类D是独立实现 直接履行接口契约,无中间层 继承实现接口的抽象类 子类E和F的实例可视为接口I的类型,同时共享抽象类的公共方法 抽象类是接口I的实现类,子类继承抽象类 通过抽象类履行接口契约,子类可扩展或覆盖 4. 设计原则与扩展性
模式 开闭原则 单一职责原则 里氏替换原则 扩展性 继承接口的实现类 修改父类B可能违反开闭原则(影响子类A) 父类B可能承担过多职责(如同时实现接口和业务逻辑) 子类A需能替换父类B而不破坏程序逻辑 新增子类需继承现有父类,扩展受限 两个类实现同一接口 符合开闭原则(新增实现类无需修改现有代码) 各实现类职责单一,仅关注接口方法实现 无继承关系,自然满足 新增实现类自由,扩展性强 继承实现接口的抽象类 抽象类提供公共逻辑,符合开闭原则(新增子类继承抽象类) 抽象类可分离接口实现与业务逻辑,子类专注差异化 子类需能替换抽象类而不破坏程序逻辑 通过抽象类统一扩展点,扩展便捷 三种方式的对比总结
适用场景与区别
- 类继承接口的实现类:适用于需要重用现有实现的情况,子类可以扩展或修改父类的实现
- 两个类实现同一个接口:适用于不同类有完全不同实现的情况,强调多态性
- 继承实现接口的抽象类:适用于有部分共同实现但又有差异的情况,平衡代码复用和灵活性
设计考虑
- 如果需要最大程度的代码复用,选择第一种或第三种方式
- 如果需要最大程度的灵活性,选择第二种方式
- 如果需要在多个类间共享一些公共代码,但同时允许不同实现,选择第三种方式