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

目录

接口与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.mzph.cn/bicheng/71902.shtml

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

相关文章

C++程序员内功修炼——Linux C/C++编程技术汇总

在软件开发的宏大版图中&#xff0c;C 语言宛如一座巍峨的高山&#xff0c;吸引着无数开发者攀登探索。而 Linux 操作系统&#xff0c;以其开源、稳定、高效的特性&#xff0c;成为了众多开发者钟爱的开发平台。将 C 与 Linux 相结合&#xff0c;就如同为开发者配备了一把无坚不…

数据库索引:缺点与类型全解析

在数据库的世界里&#xff0c;索引就像是一本书的目录&#xff0c;它能帮助我们快速定位到所需的数据&#xff0c;极大地提升查询效率。然而&#xff0c;就如同任何事物都有两面性一样&#xff0c;索引也并非完美无缺。今天&#xff0c;我们就来深入探讨一下索引的缺点以及常见…

【python】提取word\pdf格式内容到txt文件

一、使用pdfminer提取 import os import re from pdfminer.high_level import extract_text import docx2txt import jiebadef read_pdf(file_path):"""读取 PDF 文件内容:param file_path: PDF 文件路径:return: 文件内容文本"""try:text ext…

嵌入式八股文(五)硬件电路篇

一、名词概念 1. 整流和逆变 &#xff08;1&#xff09;整流&#xff1a;整流是将交流电&#xff08;AC&#xff09;转变为直流电&#xff08;DC&#xff09;。常见的整流电路包括单向整流&#xff08;二极管&#xff09;、桥式整流等。 半波整流&#xff1a;只使用交流电的正…

精选案例展 | 智己汽车—全栈可观测驱动智能化运营与成本优化

本案例为“观测先锋 2024 可观测平台创新应用案例大赛”精选案例&#xff0c;同时荣获IT168“2024技术卓越奖评选-年度创新解决方案”奖。 项目背景 近年来&#xff0c;中国汽车行业进入转型升级阶段&#xff0c;智能网联技术成为行业发展的核心。车联网、自动驾驶等技术的加速…

速通HTML

目录 HTML基础 1.快捷键 2.标签 HTML进阶 1.列表 a.无序列表 b.有序列表 c.定义列表 2.表格 a.内容 b.合并单元格 3.表单 a.input标签 b.单选框 c.上传文件 4.下拉菜单 5.文本域标签 6.label标签 7.按钮标签 8.无语义的布局标签div与span 9.字符实体 HTML…

【Python模块】——pymysql

pymysql是python操作mysql的标准库&#xff0c;可以通过pip install快速导入pymysql包操作数据库 使用pymysql操作mysql 简单demo import pymysql connect pymysql.connect(host"localhost",port3306,user"root",password"root",database&quo…

IP离线库助力破解网络反诈难题

毫秒级响应识别异常访问 IP离线库集成全球全量IP地址的详细信息&#xff0c;包括地理地址查询、运营商、经纬度、代理识别等多种维度数据。例如&#xff1a; 当用户账号频繁从北京、越南等多地IP登录时&#xff0c;系统将自动触发风险预警&#xff1b; 检测到访问IP为已知机…

lattice hdl实现spi接口

在lattice工具链中实现SPI接口通常涉及以下步骤: 定义硬件SPI接口的管脚。配置SPI时钟和模式。编写SPI主机或从机的控制逻辑。 展示了如何在Lattice工具链中使用HDL语言(例如Verilog)来配置SPI接口: lattice工程 顶层:spi_slave_top.v `timescale 1ns/ 1ps module spi_…

Spring 循环依赖解析与解决方案

文章目录 1. 什么是循环依赖&#xff1f;1.1 概念解析1.2 示例代码 2. 循环依赖的类型2.1 构造器循环依赖&#xff08;不可解决 ❌&#xff09;2.2 Setter 方式或 Autowired 方式的循环依赖&#xff08;可解决 ✅&#xff09; 3. 解决循环依赖的方式3.1 方式一&#xff1a;使用…

Cesium@1.126.0,创建3D瓦片,修改样式

第一步&#xff1a;添加3D建筑 Cesium.createOsmBuildingsAsync()这是一个异步方法&#xff0c;所以要写在一个异步函数里 创建一个函数 const create3DBuilding async (viewer) > {try {// 添加3D建筑const tileset await Cesium.createOsmBuildingsAsync();viewer.scen…

力扣-贪心-1005 k次取反后最大化的数组和

思路 找到绝对值最大的&#xff0c;然后如果是负数就变成正的&#xff0c;所有数遍历完之后&#xff0c;有两种情况&#xff0c;一种是k已经为0了&#xff0c;不需要再取反了&#xff0c;一种是所有数都为正数&#xff0c;k不为0&#xff0c;此时对绝对值最小的数操作即可 代…

vue2项目打包后js文件过大, 首次加载缓慢

vue2项目打包后js文件过大, 首次加载缓慢 安装插件 npm i compression-webpack-plugin6.1.1 -D配置vue.config.js const CompressionWebpackPlugin require(compression-webpack-plugin)module.exports {configureWebpack: {plugins:[new CompressionWebpackPlugin({filen…

高级SQL技术在Python项目中的应用:ORM与深度性能优化

引言 在现代Python项目开发中,数据库交互远不止是数据的简单存取,它已成为构建高性能、可维护应用的核心瓶颈和关键能力所在。 仅仅依赖基础SQL查询,虽然入门简单,却难以应对日益增长的应用挑战。这些挑战主要体现在以下几个方面: 性能瓶颈: 数据量剧增: 从百万到数十亿乃…

基于 C++ Qt 的 Fluent Design 组件库 QFluentWidgets

简介 QFluentWidgets 是一个基于 Qt 的 Fluent Designer 组件库&#xff0c;内置超过 150 个开箱即用的 Fluent Designer 组件&#xff0c;支持亮暗主题无缝切换和自定义主题色。 编译示例 以 Qt5 为例&#xff08;Qt6 也支持&#xff09;&#xff0c;将 libQFluentWidgets.d…

抖音视频如何下载保存去水印

随着短视频平台的兴起&#xff0c;抖音作为国内最受欢迎的短视频平台之一&#xff0c;吸引了大量用户上传和观看各种创意视频。许多用户在浏览抖音视频时&#xff0c;往往会想要保存一些有趣或精彩的视频片段&#xff0c;但抖音视频通常会有水印&#xff0c;影响观看体验。为了…

React 源码揭秘 | 更新队列

前面几篇遇到updateQueue的时候&#xff0c;我们把它先简单的当成了一个队列处理&#xff0c;这篇我们来详细讨论一下这个更新队列。 有关updateQueue中的部分&#xff0c;可以见源码 UpdateQueue实现 Update对象 我们先来看一下UpdateQueue中的内容&#xff0c;Update对象&…

[SQL] 事务的四大特性(ACID)

&#x1f384;事务的四大特性 以下就是事务的四大特性&#xff0c;简称ACID。 原子性&#x1f4e2;事务时不可分割的最小操作单元&#xff0c;要么全部成功&#xff0c;要么全部失败。一致性&#x1f4e2;事务完成后&#xff0c;必须使所有的数据都保持一致隔离性&#x1f4e2…

DeepSeek 提示词:基础结构

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

如何使用 Python 连接 MySQL 数据库?

在Python开发中&#xff0c;连接MySQL数据库是一个常见的需求。 我们可以使用多种库来实现这一功能&#xff0c;其中最常用的是mysql-connector-python和PyMySQL。 下面我将详细介绍如何使用这两个库来连接MySQL数据库&#xff0c;并提供一些实际开发中的建议和注意事项。 1…