热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

建议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个建议》陆敏技


推荐阅读
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • Hyperledger Fabric 1.4 节点 SDK 快速入门指南
    本文将详细介绍如何利用 Hyperledger Fabric 1.4 的 Node.js SDK 开发应用程序。通过最新版本的 Fabric Node.js SDK,开发者可以更高效地构建和部署基于区块链的应用,实现数据的安全共享和交易处理。文章将涵盖环境配置、SDK 安装、示例代码以及常见问题的解决方法,帮助读者快速上手并掌握核心功能。 ... [详细]
  • C#编程中按钮控件的使用与优化 ... [详细]
  • 本文源自极分享,详细内容请参阅原文。技术债务如同信用卡负债,随着时间推移,修复成本会越来越高,因此程序员必须对此有深刻认识。此外,团队应致力于培养一种持续维护和优化代码的文化,以减少技术债务的累积。 ... [详细]
  • 深入解析十大经典排序算法:动画演示、原理分析与代码实现
    本文深入探讨了十种经典的排序算法,不仅通过动画直观展示了每种算法的运行过程,还详细解析了其背后的原理与机制,并提供了相应的代码实现,帮助读者全面理解和掌握这些算法的核心要点。 ... [详细]
  • 本文深入探讨了层叠样式表(CSS)的核心原理与应用技巧,旨在帮助读者全面理解CSS的工作机制。从选择器、属性到布局模式,文章详细解析了CSS的关键概念,并通过实例展示了如何高效运用这些技术,提升网页设计与开发的水平。 ... [详细]
  • Android的设计模式解释器模式
    前言Android的设计模式系列文章介绍,欢迎关注,持续更新中:Android的设计模式-设计模式的六大原则创建型模式:A ... [详细]
  • 一.名称二.问题(为了解决什么问题)很好辨认,举一些常见的例子:猫鼠游戏广播收音机事件监听等等三.解决方案࿰ ... [详细]
  • 点击上方“新机器视觉”,选择加”星标”或“置顶”重磅干货,第一时间送达很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间。去年有过一段时间的集中学习,做 ... [详细]
  • 装饰模式(Deocrator)     动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。    所谓装饰,就是一些对象给主题 ... [详细]
  • 第四单元和课程总结:简单的架构设计意识
    一、第四单元架构设计总结第一次作业由于需要按名查找类图模型,于是建立"Class"类进行管理由于方法具有参数导致类中存在二级结构 ... [详细]
  • Unit4博客&课程总结Unit4作业的架构设计本单元作业的设计我分为了三个模块处理:模型构建+预处理+任务函数,前两部分即为整个图的完整构建,第三部分即为实现题目要求的查询方法。 ... [详细]
  • 用户登录 ... [详细]
  • Visualizing and Understanding Convolutional Networks(ZFNet网络)论文阅读笔记
    VisualizingandUnderstandingConvolutionalNetworksZFNet网络架构论文阅读笔记2022.4.4论文地址https:arxiv ... [详细]
  • 这家安全厂商避谈“软件定义”,我却要为它的“反骨”点赞
    点击上方“中国云报”可直接关注!已经成立了9年的迪普科技,今年第一次举办大规模的合作伙伴大会。4月20日,以“创享未来,诚献 ... [详细]
author-avatar
墨镜空间新
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有