博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第18条:尽量使用不可变对象
阅读量:7019 次
发布时间:2019-06-28

本文共 1397 字,大约阅读时间需要 4 分钟。

1、设计类的时候,应充分运用属性来封装数据。

 

2应该尽量把对外公布出来的属性设为只读,而且只在确有必要时才将属性对外公布。

3若属性仅可于对象内部修改,则在“class-continuation分类”中将其由readonly属性扩展为readwrite属性。

这种做法下,如果该属性是nonatomic,那么可能会产生“竞争条件”(race condition, 竞态条件)。在对象内部写入属性时,对象外的观察者也许正读取该属性。若想避免此问题,可以在必要时通过“派发队列”(dispatch queue,参见第41条)等手段,将(包括对象内部的)所有数据存取操作都设为同步操作。

a)现在,只能于实现代码内部设置这些属性了。其实更准确地说,在对象外部,仍然能通过“键值编码”(Key-Value Coding, KVC)技术设置这些属性值。这样做等于违规地绕过了本类所提供的API。

b)还可以使用类型信息查询功能查出属性属性所对应的实例变量在内存布局中的偏移量,以此来人为设置这个实例变量的值。这样做绕过本类的公共API还要不合规范。

上面额外的加入了绕过公共API来设置属性的两种方式。

但这是一种破坏,可能出现问题。所以建议,还是尽量编写不可变的对象。

 

4不要把可变的collection作为属性公开,而就提供相关的方法,以此修改对象中的可变collection。

例:

.h
Person 类中
有一个属性
@property(nonatomic, strong, readonly)NSSet *friends;
两个方法
- addFriend
- removeFriend

.m

变量
NSMutableSet *_internalFriends;
- (NSSet*)friends {
  return [_internalFriends copy];
}

- addFriend {

  _internalFriends
}
- removeFriend {
  _internalFriends
}

也可以直接用NSMutableSet来实现friends属性,令该类不借助addFriend: removeFriedn: 方法而直接操作此属性。
但是,这种过分解耦(decouple)数据的做法很容易出bug。比方说,在添加或删除朋友时,Person对象可能还要执行其他相关操作,若是采用这种做法,那就等于直接从底层修改了其内部用于存放朋友对象的set。在Person对象不知情时,直接从底层修改set可能会令对象内的各数据之间互不一致。

所以建议:不要在返回的对象上查询类型以确定其是否可变。

例:
  NSSet *friends = person.friends;
  if ([friends isKindOfClass:[NSMutableSet class]]) {
    NSMutableSet *mutableFriends = (NSMutableSet*)firends;
    // .....
  }
应该竭力避免这种做法。不要假设friends所用的那个NSSet一定是可变的。
5这依然说明:不宜从底层直接修改对象中的数据。

 

转载于:https://www.cnblogs.com/Pikdays/p/5734098.html

你可能感兴趣的文章
ubuntu16.04下python2、python3环境选择与python升级(pip版本切换)
查看>>
topcoder srm 435 div1
查看>>
Java读取文本指定的某一行内容的方法
查看>>
leetcode--Best Time to Buy and Sell Stock II
查看>>
Could not load file or assembly 'System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral..
查看>>
php 调用 web Server(短信接口示例)
查看>>
bootstrap-table组合表头
查看>>
蓝桥杯 全球变暖(dfs)
查看>>
[UML]UML系列——类图Class
查看>>
机器学习之支持向量机(Support Vector Machine)
查看>>
模型小型化小结
查看>>
fopen()和fclose()
查看>>
虹软arcface人脸识别集成到项目中
查看>>
[c语言]运算符的优先级与结合性
查看>>
C++ Studio (二) ----- atoi()函数的实现 (自己编写功能)
查看>>
NO.8:绝不在构造或者析构过程中调用virtual函数
查看>>
WinForm 调用WebService 隐藏服务器IP地址之真假美猴王~!O(∩_∩)O哈哈~
查看>>
mysql之命令行导入导出
查看>>
pythonbrew, pythonz, virtualenv
查看>>
没有mysql支持时的替代方案
查看>>