建议103:区分组合和继承的应用场合

继承所带来的多态性虽然是面向对象的一个重要特性,但这种特性不能在所有的场合中滥用。继承应该被当做设计架构的有用补充,而不是全部。

组合不能用于多态,但组合使用的频率却要远远高于继承。

继承UML图如下:

对应的代码如下:

    abstract class Stream
{
//省略
} class FileStream:Stream
{
//省略
} class MemoryStream : Stream
{
//省略
}

组合UML图如下:

对应代码如下:

    class Context
{
//省略
} class CultureInfo
{
//省略
} class Thread
{
private Context m_Context;
private CultureInfo m_CultureInfo;
//省略
}

从设计的角度来看,继承代表的是“Is a”,组合代表的是“Has a”。FileStream和MemoryStream都是(Is a)Stream,而对于线程Thread来说,它拥有(Has a)线程上下文Context和区域信息CultureInfo。这是最重要的区别,任何时候,设计理念上的因素总是排在第一位。

继承不仅仅是指继承自某个类型(class),也可以指继承自某个接口(interface)。继承最大的优点就是多态,这也奠定了面向抽象编程的基础。继承提高了代码的复用性。组合显然不具备这种特性。

从语法角度来看,继承易于扩展。基类一旦扩展一个具有public、internal、protected访问修饰符的接口,所有的子类都会自动拥有其接口,组合则不能。组合要拥有任何对象的行为,必须手动编码。以Thread为例,组合要拥有CultureInfo的行为,必须首先在自身内部包含一个CultureInfo字段,如下:

    class CultureInfo
{
//省略
public void OtherMethod()
{ }
} class Thread
{
private Context m_Context;
private CultureInfo m_CultureInfo;
//省略 public void OtherMethod()
{
m_CultureInfo.OtherMethod();
}
}

到目前为止,似乎一直在说继承的优点。事实上,继承的以上优点,正好又是它的缺点。子类天然具有基类的公开接口,而这正好破换了面向对象的“封装性”。我们显然不需要每一层的类型都具有上层的所有接口。一个类,如果其继承体系达到3层(当然,凡事都有例外,WPF体系中的控件集成体系,以Shape为例,多达7层),就可以考虑停止了。如果不停止,对调用者来说,最底层的类型会有多少公开的方法和属性呢?答案是最底层的类型会拥有所有上层类型的开放接口。随着项目的发展,组合的优势会逐渐体现出来,它良好的封装性使类型可以对外宣布:我只做一件事。

组合的另一个优势是,它可以组合多个其他类型。如果组合太多的类型,就意味着当前的类很可能做了太多的事情,它就需要拆分成两个类了。继承不具有这样的特性,在C#中,子类只能有一个基类(接口则放开这种限制,子类可以继承自多个接口)。

应当根据实际情况考虑是使用继承还是组合。一般来讲,组合更能满足大部分的应用场景。不要为了让代码看起来像“面向对象”,而滥用继承。

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

编写高质量代码改善C#程序的157个建议——建议103:区分组合和继承的应用场合的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议[1-3]

    原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...

  2. 读书--编写高质量代码 改善C#程序的157个建议

    最近读了陆敏技写的一本书<<编写高质量代码  改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...

  3. 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试

    建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...

  4. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

  5. 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码

    建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...

  6. 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣

    建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...

  7. 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释

    建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...

  8. 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释

    建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...

  9. 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量

    建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...

  10. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

随机推荐

  1. php redis安装使用

    下载redis-windows-master.解压点击redis-server.exe运行服务端 redis设置访问密码 修改redis.conf文件配置, # requirepass foobare ...

  2. IDA Pro 权威指南学习笔记(十四) - 操纵函数

    IDA 无法定位一个函数调用,由于没有直接的方法到达函数,IDA 将无法识别它们 IDA 可能无法正确确定函数的结束部分,需要手动干预,以更正反汇编代码中的错误 如果编译器已经将函数分割到几个地址范围 ...

  3. [Cpp primer] Library string Type

    In order to use string type, we need to include the following code #include<string> using std: ...

  4. Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡

    转载:http://blog.csdn.net/congcong68/article/details/41113239 互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架 ...

  5. leetcode289

    public class Solution { public void GameOfLife(int[][] board) { ) - ; ].GetLength() - ; var list = n ...

  6. python时间戳、日期、时间转换

    1.str转时间戳 # 字符类型的时间 tss1 = '2013-10-10 23:40:00' # 转为时间数组 timeArray = time.strptime(tss1, "%Y-% ...

  7. 简单例子让你很好的理解:协议与委托 (Protocol and Delegate)

    1 协议: 协议,类似于Java或C#语言中的接口,它限制了实现类必须拥有哪些方法. 它是对对象行为的定义,也是对功能的规范. 示例: 1 2 3 4 5 6 7 8 9 // GoodChild.h ...

  8. Git Hook 同步服务器代码

    参考并转载自: http://www.embbnux.com/2014/09/05/git_server_let_code_auto_deploy/ http://www.chenyudong.com ...

  9. 前端开发之JavaScript基础篇二

    主要内容: 1.流程控制条件语句和switch语句 2.for循环和while循环 3.Break语句和Continue语句 4.数组和数组常用方法 5.函数 6.对象 一.流程控制条件语句和swit ...

  10. 【转】H5+css布局+js+前端和移动端ui+其他汇总

    无意间发现一个博客比较好,由于内容比较多,就把链接转过来,先保存着方便看的时候看. 感谢博主“张果” +++++++++++++++++++++++++++++++++++++++++++++++++ ...