理解值与引用[学习]

简介:

面向对象分析和设计需要区分对象的值语义与引用语义。

我的一块钱和你的一块钱相等,这是

20岁的我和30岁的我是同一个人,这是语义

值对象包括2大特征:表示和运算。比如:3这个整数在计算机内部用二进制11表示,可以参与+,-,*,/等运算;

引用对象包括3大特征:标识、状态 和 行为。比如:person对象拥有不变的标识,并可通过行为改变状态。

值对象的同一性建立在表示的基础上,而引用对象的同一性建立在标识的基础上。

值对象只能被动地参与运算,引用对象拥有主动的行为。

struct 和 class 是 OOP 语言为分别表达值语义和引用语义所提供的语法机制。

C#中 struct 可以实现接口,可以定义方法;但从语义角度,对于 struct 类型的 DateTime 对象 today,today.AddDays(1) 的语义是today 和 1 参与 AddDays 运算得出一个新的日期值。

由于值对象的同一性建立在表示的基础上,而引用对象的同一性建立在标识的基础上。值对象从语义上是不可变的,而引用对象从语义上是不可拷贝的。但在 实际实现中由于性能考虑常常会用引用语法来实现值语义,比如:C# 的 string 是值语义,但却是引用语法;类似的,flyweight 模式被共享的小对 象也是引用语法表达值语义。由于值语义的不可变性要求,用引用语法模拟值语义常常会加上不可变的限制,比如:C# 的 string 对象在参与 + 运算本身并不 改变,而是产生一个新 string 对象作为结果。这种通过不可变引用语法来模拟值语义的手段在不支持 struct 的 Java 中更加常用。而在 C++ 中,虽 然提供了 struct 和class,但二者在语法上都是值语法(可拷贝);所以,在 C++ 中常常会为 class 加上不可拷贝的限制明确引用语义,强制使用指针或引用的方式使用对象。

在使用上,值对象通常用于表示引用对象的某一属性,比如:颜色RGB,字体类型,出生日期。

下面通过一个例子进一步体会值与引用的区别:

复制代码
class Person{
private DateTime m_birthday;
public DateTime GetBirthday(){
return m_birthday;
}
}
复制代码

值类型的 m_birthday 对象是为了描述引用类型 Person 某一方面属性的。

如果 DateTime 是 class,那么 GetBirthday 只需要返回引用;

如果 DateTime 是 struct,那么 GetBirthday 就是值拷贝。

从性能角度,返回引用优于值拷贝;但从设计角度,返回引用使得外部可以直接修改 Person 对象的内部状态,破坏了封装。

如果是 Java,由于不支持 struct,所以只能在引用语法的基础上模拟值语义,比如:返回一份 clone。

显然,由于 C# 对 struct 的直接支持,一旦明确了 m_birthday 的值语义,那么语法的支持直接而简洁。

确定领域对象是值语义还是引用语义是分析设计阶段的事情,其原则是基于值对象和引用对象的特征。

而对于 struct 和 class 的选择是实现阶段的事情。

假如分析设计确定领域对象是引用语义,那么语法选择只有 class,不可能去选择 struct ;

而如果领域对象是值语义,比如 dateTime 或 string,那么语法选择可以是 struct 也可以是 class。struct 是默认的选择,即使由于性能原因选择了class,还是需要像 string 一样注意设计细节去表达值语义。我们提倡的是在明确领域对象的语义后,应该首选默认选项,即用struct 表示值,用 class 表示引用。默认不需要理由,不用默认才需要理由。

参考:

《冒号课堂--编程范式与OOP思想》

《Effective C#》

《领域驱动设计精简版》




本文转自钢钢博客园博客,原文链接:http://www.cnblogs.com/xugang/archive/2010/07/29/1787580.html,如需转载请自行联系原作者

相关文章
|
2天前
|
存储 JavaScript 前端开发
JavaScript基础
本节讲解JavaScript基础核心知识:涵盖值类型与引用类型区别、typeof检测类型及局限性、===与==差异及应用场景、内置函数与对象、原型链五规则、属性查找机制、instanceof原理,以及this指向和箭头函数中this的绑定时机。重点突出类型判断、原型继承与this机制,助力深入理解JS面向对象机制。(238字)
|
1天前
|
云安全 人工智能 安全
阿里云2026云上安全健康体检正式开启
新年启程,来为云上环境做一次“深度体检”
1470 6
|
3天前
|
安全 数据可视化 网络安全
安全无小事|阿里云先知众测,为企业筑牢防线
专为企业打造的漏洞信息收集平台
1304 2
|
3天前
|
缓存 算法 关系型数据库
深入浅出分布式 ID 生成方案:从原理到业界主流实现
本文深入探讨分布式ID的生成原理与主流解决方案,解析百度UidGenerator、滴滴TinyID及美团Leaf的核心设计,涵盖Snowflake算法、号段模式与双Buffer优化,助你掌握高并发下全局唯一ID的实现精髓。
319 160
|
3天前
|
人工智能 自然语言处理 API
n8n:流程自动化、智能化利器
流程自动化助你在重复的业务流程中节省时间,可通过自然语言直接创建工作流啦。
365 4
n8n:流程自动化、智能化利器
|
11天前
|
机器学习/深度学习 安全 API
MAI-UI 开源:通用 GUI 智能体基座登顶 SOTA!
MAI-UI是通义实验室推出的全尺寸GUI智能体基座模型,原生集成用户交互、MCP工具调用与端云协同能力。支持跨App操作、模糊语义理解与主动提问澄清,通过大规模在线强化学习实现复杂任务自动化,在出行、办公等高频场景中表现卓越,已登顶ScreenSpot-Pro、MobileWorld等多项SOTA评测。
1476 7
|
5天前
|
人工智能 API 开发工具
Skills比MCP更重要?更省钱的多!Python大佬这观点老金测了一周终于懂了
加我进AI学习群,公众号右下角“联系方式”。文末有老金开源知识库·全免费。本文详解Claude Skills为何比MCP更轻量高效:极简配置、按需加载、省90% token,适合多数场景。MCP仍适用于复杂集成,但日常任务首选Skills。推荐先用SKILL.md解决,再考虑协议。附实测对比与配置建议,助你提升效率,节省精力。关注老金,一起玩转AI工具。
|
1天前
|
Linux 数据库
Linux 环境 Polardb-X 数据库 单机版 rpm 包 安装教程
本文介绍在CentOS 7.9环境下安装PolarDB-X单机版数据库的完整流程,涵盖系统环境准备、本地Yum源配置、RPM包安装、用户与目录初始化、依赖库解决、数据库启动及客户端连接等步骤,助您快速部署运行PolarDB-X。
228 1
Linux 环境 Polardb-X 数据库 单机版 rpm 包 安装教程
|
12天前
|
人工智能 Rust 运维
这个神器让你白嫖ClaudeOpus 4.5,Gemini 3!还能接Claude Code等任意平台
加我进AI讨论学习群,公众号右下角“联系方式”文末有老金的 开源知识库地址·全免费
1342 17
|
3天前
|
自然语言处理 监控 测试技术
互联网大厂“黑话”完全破译指南
互联网大厂黑话太多听不懂?本文整理了一份“保姆级”职场黑话词典,涵盖PRD、A/B测试、WLB、埋点、灰度发布等高频术语,用大白话+生活化类比,帮你快速听懂同事在聊什么。非技术岗也能轻松理解,建议收藏防踩坑。
274 161

热门文章

最新文章