《Effective Objective-C》阅读笔记(中)

news2025/2/26 12:53:41

目录

接口与API设计

用前缀避免命名空间冲突

提供“全能初始化方法”

实现description方法

尽量使用不可变对象

使用清晰而协调的命名方式

方法命名

​编辑类与协议命名

为私有方法名加前缀

理解OC错误模型

理解NSCopying协议

协议与分类

通过委托与数据源协议进行对象间通信

将类的实现代码分散到便于管理的数个分类之中

总是为第三方类的分类名称加前缀

​使用"class-continuation分类"隐藏实现细节

通过协议提供匿名对象


接口与API设计

用前缀避免命名空间冲突

为了避免“重名符号错误”,应当为所有名称都加上适当前缀,可以与公司、程序或二者皆有关。

但使用Cocoa创建程序时,要注意Apple保留使用所有“两字母前缀”的权利,所以开发者使用的前缀应该是三个字母的

不仅是类,还有C函数的名字也应加上前缀

如果是开发第三方库,那么对于所有包含的第三方库代码都加上自己的前缀。

提供“全能初始化方法”

可以为对象提供必要信息以便其能完成工作的初始化方法叫做“全能初始化方法”。

在上图方法中,initWithTimeIntervalSinceReferenceDate:便是全能初始化方法。

当一个类有多个初始化方法时,仍要选定一个作为全能初始化方法,其他初始化方法都调用它。

只有在全能初始化方法中,才会存储内部数据,这样的话,当底层数据存储机制改变时,只需修改此方法的代码就好。

如果子类的全能初始化方法与超类方法的名称不同,那么总应覆写超类的全能初始化方法。

实现description方法

在自定义类中,description的默认实现是打印类名和地址,输出信息如下:

这时我们应尽量将输出信息改为一个有意义的字符串,用来描述这个实例。有个简单的方法,就是借助NSDictionary的description方法。此方法输出的信息的格式如下:

字符串可以采用如下格式:

若想在调试时打印更详尽的描述信息,应实现debugDescripption方法。

尽量使用不可变对象

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

有时可能想修改封装在对象内部的数据,但是不想让这些数据为外人所改动,这种情况下通常做法是将readonly重新声明为readwrite,这一操作应该在"class-continuation分类"中完成。

在定义类的公共API时,还应注意:对象里表示各种collection的那些属性应该设成可变的,还是不可变的。

比如:我们用某个类来表示个人信息,该类中还存放了一些引用指向此人的朋友,开发者可以添加或删除朋友,那这个属性就要用可变的set来实现。这种情况下,通常应该提供一个readonly属性供外界使用,返回一个不可变的set,这个set是内部可变set的一份拷贝。比如下面这份代码:

使用清晰而协调的命名方式

OC当中方法与变量名采用“驼峰式大小写命名法”,而类名首字母大写,并且有两三个前缀字母。

方法命名

命名方法时,应当使方法像个日常用语中的句子,准确传达方法所执行的任务,然而方法名不能长得太过分,应尽量言简意赅。

类与协议命名

类与协议的名称应加上前缀,并且应该像给方法起名一样组织好词句,使从左至右比较通顺。

为私有方法名加前缀

在编写私有方法时,最好使用前缀将私有方法标注出来,前缀最好包含下划线与字母p。

要注意不应该直接使用下划线作为私有方法的前缀,因为苹果公司喜欢单用一个下划线作为私有方法的前缀,使用一个下划线有可能会无意中覆写超类中的其他方法。

理解OC错误模型

自动引用计数不是“异常安全”的,并且即使不用ARC,也很难写出在抛出异常时不会导致内存泄漏的代码。所以OC语言当中,异常只用于极其严重的错误,抛出异常之后,应用程序应该退出,也就无需考虑恢复问题了

在出现不那么严重的错误时,OC语言所用的编程范式为:令方法返回nil/0,或是使用NSError,以表明其中有错误发生。

NSError的用法更加灵活,NSError对象里封装了三条信息:

Error domain:错误发生的范围,也就是产生错误的根源。

Error code:独有的错误代码,用以指明在某个范围内具体发生了何种错误。

User info:有关此错误的额外信息。

NSError有两种常见用法,一种是通过委托协议来传递错误,另一种是经由方法的“输出参数”返回给调用者。

理解NSCopying协议

OC中如果想令自己的类支持拷贝操作,那就要实现NSCopying协议,该协议只有一个方法:

这里zone参数不用考虑,使用默认参数即可。比如游客表示个人信息的类,可以声明遵从NSCopying协议:

有时需要获取可变的拷贝,则应遵守NSMutableCopying协议,该协议也只定义了一个方法:

当对象需要深拷贝时,可考虑吧新增一个专门执行深拷贝的方法

协议与分类

通过委托与数据源协议进行对象间通信

OC开发中经常使用一种“委托模式”,主旨是:定义一套接口,某对象若想接受另一个对象的委托,则需遵从此接口,以成为其“委托对象”,而这另一个对象,则可以给其委托对象回传一些信息,也可以在发生相关事件时通知委托对象。一般通过协议来实现委托模式。

用一张图来演示委托模式的概念:

这里EOCDataModel1就是作为EOCNetwirkFetcher的委托对象。

但是要注意,类中存放委托对象的属性需定义成weak,而非strong:

@interface EOCNetworkFetcher : NSObject
@property (nonatomic, weak) id <EOCNetworkFetcherDelegate> delegate;
@end

因为通常delegate要持有本对象,若本对象也持有delegate,那么就会引入保留环。

实现委托对象可以在接口中声明,也可以在“class-continuation分类”中声明。如果要向外界公布此类实现了某协议,那么就在接口中声明,如果是委托协议,通常只在类内部使用,一般在"class-continuation分类"里声明。

还有另一种,令某类经由协议中接口获取所需的数据,被称为“数据源模式”。

若有必要,可实现含有位段的结构体,将委托对象是否能相应相关协议方法这一信息缓存至其中。

将类的实现代码分散到便于管理的数个分类之中

当类中存在大量方法的代码时,可以通过OC的分类机制,把类代码按逻辑划入几个分区中。

比如下面这个管理个人信息的类:

可以把不同的方法放入不同分类中:

这些分类可以全部放在一个实现文件中,但当存在许多分类时,最好每个分类提取到各自的文件中去。以EOCPerson为例,可以拆分成下列这几个文件:

私有方法应归入名叫Private的分类中,以隐藏实现细节。

总是为第三方类的分类名称加前缀

我们经常通过分类为无源码的既有类添加方法,这时就容易出现命名冲突的问题。我们应该为分类和方法添加了前缀。

比如为NSString添加分类处理HTTP URL有关的字符串。

我们为其加上前缀:

使用"class-continuation分类"隐藏实现细节

class-continuation分类"和普通的分类不同,他必须定义在其所接续的那个类的实现文件里,这是唯一能声明实例变量的分类。

这种分类在实现文件中格式如下:

通过这种分类可以获得隐藏程度更好的私有方法和私有变量。

除了获得隐藏变量和方法之外,使用这种分类还可以将只读的属性扩展为可读写的,以便在类的内部设置其值。

还有一种用法是,当对象所遵从的协议只应视为私有,则可在该分类中声明

通过协议提供匿名对象

有时,我们可以把返回的对象设计为遵从某协议的id类型,这样的话,想要隐藏的类名就不会出现在API之中了。若接口背后有多个不同的实现类,又不想指明具体使用哪个,可以考虑用这个方法,此概念被称为“匿名对象”。

有时对象类型不重要,重要的是有没有实现某些方法,在此情况下,也可以使用这些“匿名类型”来表达这一概念。

比如对受委托者的定义:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2306366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hbase客户端API——语句大全

目录 创建表&#xff1a; 插入数据&#xff1a; 删除数据&#xff1a; 修改数据&#xff1a; 查询数据&#xff1a;Get 查询数据&#xff1a;Scan 查询数据&#xff1a;过滤查询 创建表&#xff1a; 检验&#xff1a; 插入数据&#xff1a; 验证 一次多条数据插入 验证&…

MQ(Message Queue)

目录 MQ(Message Queue)基本概念 为什么要使用消息队列&#xff1f; 使用消息队列有什么缺点&#xff1f; 如何保证消息不丢失?(如何保证消息的可靠性传输?/如何处理消息丢失的问题?) 通用的MQ场景&#xff1a; RabbitMQ如何保证消息不丢失&#xff1f; 生产者丢数据…

计算机网络————(三)

前文二 前文一 Websocket协议 是一种存在TCP协议之上的协议 当客户端需要了解服务器是否更新就需要不断给客户端发送请求询问是否更新&#xff0c;这行会造成服务端压力很大 而Websocket相当于服务器一旦更新了就会给客户端发送消息表明自己更新了&#xff0c;类似客户端订阅…

【音视频】音视频录制、播放原理

一、音视频录制原理 通常&#xff0c;音视频录制的步骤如下图所示&#xff1a; 我们分别从音频和视频开始采样&#xff0c;通过麦克风和摄像头来接受我们的音频信息和图像信息&#xff0c;这通常是同时进行的&#xff0c;不过&#xff0c;通常视频的采集会比音频的采集慢&…

deepseek 导出导入模型(docker)

前言 实现导出导入deepseek 模型。deepseek 安装docker下参考 docker 导出模型 实际生产环境建议使用docker-compose.yml进行布局&#xff0c;然后持久化ollama模型数据到本地参考 echo "start ollama" docker start ollama#压缩容器内文件夹&#xff0c;然后拷贝…

基于Redis 的分布式 session 图解

Redis 分布式 Session 工作原理 1. 传统 Session 的问题 在传统单服务器环境中&#xff0c;HTTP Session 存储在应用服务器的内存中。这在分布式系统中会导致问题&#xff1a; 用户的请求可能被分发到不同服务器&#xff0c;导致会话不一致服务器宕机会导致会话丢失需要依赖…

DeepSeek-R1本地部署保姆级教程

一、DeepSeek-R1本地部署配置要求 &#xff08;一&#xff09;轻量级模型 ▌DeepSeek-R1-1.5B 内存容量&#xff1a;≥8GB 显卡需求&#xff1a;支持CPU推理&#xff08;无需独立GPU&#xff09; 适用场景&#xff1a;本地环境验证测试/Ollama集成调试 &#xff08;二&a…

【deepseek】本地部署+webui访问

背景 最近deepseek很火&#xff0c;但是官网的老是被限流使用&#xff0c;还有就是自己也想着玩一玩&#xff0c;于是准备在自己电脑跑一个 直接附上结果地址mydeepseek 准备工作 windows和linux都可 我这里选择linux&#xff0c;ubuntu系统 安装ollama 看下图&#xff0…

博客系统笔记总结 2( Linux 相关)

Linux 基本使用和程序部署 基本命令 文件操作 显示当前目录下的文件 ls&#xff1a;显示当前目录下的文件 ll&#xff1a;以列表的形式展示&#xff0c;包括隐藏文件 进入目录 && 显示当前路径 cd&#xff1a;进入目录&#xff08;后面跟相对路径或者绝对路径&…

Flutter - 基础Widget

Flutter 中万物皆 Widget&#xff0c;基础Widget 同步对应 Android View. 普通文本 Text /*** 控制文本样式统一使用 style:TextStyle, 例&#xff1a;fontSize(字体大小),color(颜色),shadows(阴影)等等* 控制文本布局需单独设置&#xff1a;* textAlign(文不对齐方式)* te…

如何在 Linux 上安装和配置 Zsh

文章目录 如何在 Linux 上安装和配置 Zsh1. 安装 Zsh1.1 在 Ubuntu/Debian 上安装1.2 在 CentOS/RHEL/Fedora 上安装1.3 在 Arch Linux 上安装1.4 验证 Zsh 安装 2. 设置 Zsh 为默认 Shell2.1 验证默认 shell 3. 配置 Zsh3.1 使用 Oh My Zsh3.1.1 安装 Oh My Zsh3.1.2 启用插件…

【System Verilog and UVM基础入门26】Verdi使用教程指南

《Verdi使用教程指南 》 下载链接&#xff1a; https://download.csdn.net/download/TommiWei/90429701https://download.csdn.net/download/TommiWei/90429701 朋友你好&#xff0c;不管你是否使用过Verdi这款EDA仿真工具。 不管你是否还在寻找免费的使用教材。 不管你是否…

3dtiles平移旋转工具制作

3dtiles平移旋转缩放原理及可视化工具实现 背景 平时工作中&#xff0c;通过cesium平台来搭建一个演示场景是很常见的事情。一般来说&#xff0c;演示场景不需要多完善的功能&#xff0c;但是需要一批三维模型搭建&#xff0c;如厂房、电力设备、园区等。在实际搭建过程中&…

【STL专题】优先级队列priority_queue的使用和模拟实现,巧妙利用仿函数解决优先级

欢迎来到 CILMY23的博客 &#x1f3c6;本篇主题为&#xff1a;优先级队列priority_queue的使用和模拟实现&#xff0c;巧妙利用仿函数解决优先级 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a; C | C语言 | 数据结构与算法 | Linux…

数据开发面试:DQL,

DQL常见面试题 where 和 having 的区别 三个排序开窗函数的区别 left join 用where 筛选 和 用on筛选的区别 ON 子句&#xff1a;用于定义连接条件&#xff0c;不会丢失左表的行。 WHERE 子句&#xff1a;用于过滤连接后的结果集&#xff0c;可能会丢失左表中没有匹配的行 …

最长递增子序列(贪心算法)思路+源码

文章目录 题目[](https://leetcode.cn/problems/longest-increasing-subsequence/)算法原理源码总结题目 首先,要掌握动态规划加二分查找 算法原理 1.回顾dp的解法 状态表示:dp[i]表示:以i位置的元素为结尾的所有的子序列中,最长递增子序列的长度 状态转移方程:dp[i]= m…

Orange 开源项目 - 集成百度智能云-千帆大模型

1 集成百度智能云-千帆大模型 百度智能云-千帆ModelBuilder百度智能云千帆大模型服务与开发平台ModelBuilder&#xff08;以下简称千帆ModelBuilder&#xff09;是面向企业开发者的一站式大模型开发及服务运行平台。千帆ModelBuilder不仅提供了包括文心一言底层模型和第三方开源…

前缀和代码解析

前缀和是指数组一定范围的数的总和,常见的有两种,一维和二维,我会用两道题来分别解析 一维 DP34 【模板】前缀和 题目: 题目解析: 暴力解法 直接遍历数组,遍历到下标为 l 时,开始进行相加,直到遍历到下标为 r ,最后返回总和.这样做的时间复杂度为: O(n) public class Main …

【前端基础】Day 1 HTML

总结&#xff1a; 1. Web标准的构成 2. 基本标签 目录 1. Web标准的构成 2. 基本标签 2.1快捷键 2.2.1标题标签 2.2.2段落和换行标签 2.2.3文本格式化标签 2.2.4div和span标签 2.3.1 图像标签和路径 2.3.2路径 2.3.3超链接标签 2.4注释标签 2.5特殊字符 1. Web标准…

【前端基础】Day 2 HTML

目录 1.表格标签 2.列表标签 3.表单标签 4.综合案例 5.查阅文档 1.表格标签 <body><table align"center" border"1" cellpadding"0" cellspacing"0" width"500" height"100"><thead> …