zoukankan      html  css  js  c++  java
  • 设计原则:什么样的情况下需要引入父类?

    背景

    什么样的情况下需要引入父类?这就是今天的话题,也是对昨天的文章(设计原则:不要为了复用而使用继承)的一个补充。

    让我们站在抽象的角度思考这个问题,下面两幅图片是我们讨论的上下文。

    设计1

    设计2

    为什么引入了两个父类(Base2和Base3)?

    为了复用实现

    面对这个问题,我可能给出的一种回答是:A和B为了复用方法(行为)或数据(状态),如果我接受这个答案,那么如何应对“B和C之间的复用”,很多语言都是单实现继承的,这说明复用实现不是继承的本质原因,我对这个答案不够满意,继续思考。

    为了引入抽象

    如果我给出的答案是:为了引入抽象,这个答案本身就够抽象了,估计会被很多人批评(期望被批评),先让我简单的解释一下。

    引入了父类,在某种程度上是引入了一个继承体系,父类就是这个继承体系的抽象表示,使用者只需要关心这个抽象即可(父类),这也是“面向接口编程”的核心思想。父类定义了契约,子类实现契约,子类之间表现出多态。

    这个答案也可以这么解说:为了复用契约为了面向接口编程、为了多态

    总结:继承可以实现复用,不要为了复用而使用继承。

    如何复用B和C之间重复的代码?

    假如Base2和Base3都是合理的,如何复用B和C之间的代码?抽象的表达是:如何在不同的继承体系之间复用代码?

    让我们举个例子

    ICompareable<T> 接口定义了一个方法Compare,如果A.Compare(B)的结果为-1,表示A<B,如果为0,表示A==B,如果为1,表示A>B。

    我们将ICompareable<T>.Compare命名为“定律方法”。

    CompareableExtentions 扩张了ICompareable<T>,提供了:Less、LessEqual、Greate、GreateEqual、Equal和Between。

    我们将Less、LessEqual、Greate、GreateEqual、Equal和Between命名为“推论方法”。

    总结:在多个继承体系中,用接口继承复用“定律方法”,用掺入(C#中叫扩张方法)复用“推论方法”。

    关于掺入可以参考如下文章:

    1. PHP中实现掺入
    2. JS、C#、Java、Ruby、Python、C++中实现掺入

    备注

    每天能想明白一点东西,真是让人开心,感谢博客园和群里的兄弟们,这个问题暂时告一段落,做好否定自己的准备

  • 相关阅读:
    jsp实现登陆功能小实验
    netty
    shiro
    mybatis
    spring MVC
    spring
    集合框架面试题
    Redis面试题
    Dubbo面试题汇总
    阿里面试题
  • 原文地址:https://www.cnblogs.com/happyframework/p/3279560.html
Copyright © 2011-2022 走看看