第五章——结构体与类(实体和值)

感谢DJagger提供翻译

在领域模型驱动设计(Domain Driven Design)[1]中体现了实体的区别,每个实体都有惟一的身份(identity),而值由它的属性所决定。

NSFileHandle是一个实体的例子:它封装了一个文件描述符。如果我们想知道两个NSFileHandle类型的对象是否相同,我们可以检查他们是否引用同一个对象。文件的句柄有生命周期,会随着时间改变。如果我们有两个不同的文件句柄(各自的文件描述符不相同),即便其他属性相同,我们也要对它们区别对待,应该分别关闭这两个文件描述符。

比如NSURL就是一个——它是一种不可变的对象,通过属性确认身份。如果两个NSURL对象表示的URL相同,那么这两个对象就是相同的。URL是固定的,不会随着时间改变。

当我们要在实体和值之间做出选择时,一个最重要的问题就是:*“它需要确定的身份吗?”*在文件句柄的例子中,回答是肯定的,我们需要分开管理每个文件句柄的生命周期。而在URL的例子中,我们关心它们表示的是否是同一个URL而非同一个引用。

在几乎所有的程序中,有许多的实体扮演者重要的角色。文件描述符、通知中心、网络接口、数据库记录、输入设备、应用以及缓存都是实体,因为它们都有自己的生命周期和惟一的身份。

值在软件中也有很多的用处。URL、二进制数据、日期、错误、字符串、通知以及数字只定义了它们的属性,它们不随着时间改变。使用了不可变值的代码更好理解,不可变性直接确保了他们是线程安全的:任何不可变的的东西在线程之间共享时都是安全的。

当我们需要区分值和引用时,应用的领域是决定因素之一。举个例子,在一个展示联系人信息的应用中,地址应该被定义为值类型,它的身份就是它的值。如果有很多联系人共用一个地址,我们必然不希望改动一个人的地址信息时也改动其他人的地址。然而在拼车的应用中,我们应该会用实体来表示地址:如果多人共用一个地址,我们希望它们拼一辆车。

在Swift中定义新类型时,我们可以在结构体、枚举和类中选择。类在大多数情况下最适合实体:类在默认情况下时可变的,而且类的实例会随着时间改变它们的状态

使用值类型时,结构体通常是最适合的。我们可以通过编译器强制结构体不可变。换句话说,编译器可以保证我们的类型有值语义。在某些情况下,类也可能是值类型的最佳选择——比如我们需要与Objective-c连接。不过这时候我们需要自己保证不可变性。

当你需要在结构体和类之间做出选择时,我们建议你考虑等价性(equality)。是否根据引用比较实例是否相同,换句话说,两个有一样数据的实例会被认为是不同的吗?如果答案是肯定的话,类更加适合。 我们还可以思考一下,是否能通过包含的数据判断实例是否相同?是的话,则结构体更适合。

当与Cocoa和Objective-C对接时,我们几乎总是需要使用类。举个例子,当实现一个table view的代理时,我们只能用类,别无选择。许多的苹果框架也严重依赖于子类。然而,面对不同领域的问题,我们可能仍需要设计具有值语义的类。举个例子来说,在Core Image框架中,CIImage对象是不可改变的:他们表示了一个再不能改变的图像。

在本章的剩余部分,我们会说明结构体和类在行为上的不同,这让你更容易决定把你的类型设计为类还是结构体。

##译者注 [1]:领域模型驱动设计参考Richie的博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值