【Effective Objective - C 2.0】——读书笔记(一)

文章目录

  • 前言
  • 一、了解Objective-C语言的起源
    • OC的起源
    • 运行期组件和内存管理
  • 二、在类的头文件中尽量少引入其他头文件
    • 尽量延后引入头文件或者单独开辟一个文件
    • 向前声明
  • 三、多用字面量语法,少用与之等价的方法
  • 四、多用类型常量,少用#define预处理指令
  • 五、用枚举表示状态,选项,状态码
  • 总结


前言

最近寒假学习了【Effective Objective - C 2.0】这本书,特此总结


一、了解Objective-C语言的起源

OC的起源

OC与许多其他面向对象的语言类似,但是在很多其他方面有所差别,特别是在语法方面。因为OC使用消息结构而非函数调用。OC是消息型语言的鼻祖,消息与函数之间的区别看上去就像这样:

//Messaging(Objevtive-C)
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter2];

//Function calling(C++)
Object *obj = new Object;
obj->perform(parameter1, parameter2);

消息结构和函数调用的关键差别在于:使用消息结构的语言,其运行所应执行的代码由运行环境来决定;而使用函数调用的语言,则由编译器决定

运行期组件和内存管理

Objective-C的重要工作都由“运行期组件”(runtime component)而非编译器来完成。使用Objective-C的面向对象特性所需的全部数据结构及函数都在运行期组件里面。运行期组件本质上就是一种与开发者所编代码相链接的“动态库”(dynamic library),其代码能把开发者编写的所有程序粘合起来。

我们以一个例子来说明:

NSString *someString = @"The string";

例如上述代码,声明了一个someString 的变量,此变量为指向NSString的指针,因为OC声明变量基本上都为指针变量,所以OC对象所占内存总是分配在“堆空间”(heap space)中,而绝不会分配在“栈”(stack)上

如果再次创建一个对象Same,那么这两个对象队徽分配在堆中,它们同时指向了堆中的NSString实例

NSString *someString = @"The string";
NSString *anotherString = someString;

再说的简单点,就是对象分配在栈上,而实例分配在堆中。一些不含*的数据类型也会分配在栈中,例如CGRect

Objective-C的起源要点总结

Objective-C为C语言添加了面向对象特性,是其超集。Objective-C使用动态绑定的消息结构,也就是说,在运行时才会检查对象类型。接收一条消息之后,究竟应执行何种代码,由运行期环境而非编译器来决定。
理解C语言的核心概念有助于写好Objective-C程序。尤其是要掌握内存模型和指针。

二、在类的头文件中尽量少引入其他头文件

尽量延后引入头文件或者单独开辟一个文件

  • 将引入头文件的时机尽量延后,只在需要的时候才引入,这当然会减少编译时间,提升效率
  • 有时候必须要在头文件引入其他头文件,例如遵守某个协议并且必须实现全部细节,这个时候我们可以把该协议单独写一个文件避免了不必要的编译会延期编译效率

而当你需要实现EOCEmployer接口的全部细节时候只需要在实现文件里添加#import "EOCEmployer.h"即可:

#import "EOCPerson.h"
#import "EOCEmployer.h"

@implementation EOCPerson

@end

向前声明

  • 解决了这两个类相互引用问题
  • 相互引用:有两个类,它们都在头文件中引入了对方的头文件,两个类都进行各自的引用解析,这样就会导致“循环引用”(chicken-and-egg
    situation)。虽然我们使用#import而非#include不会导致死循环,但是这意味着两个类中有一个类无法被正确编译
  • 但是,有时候就必须引入头文件,比如继承以及遵循的协议

要点总结:

  • 除非确有必要,否则不要引入头文件。一般来说,应在某个类的头文件中使用向前声明来提及别的类(使用@class),并在实现文件中引入那些类的头文件(使用import)。这样做可以尽量降低类之间的耦合。
  • 有时无法使用向前声明,比如要声明某个类遵循一项协议。这种情况下,尽量把“该类遵循某协议”的这条声明移至 分类
    中。如果不行的话,就把协议单独放在一个头文件中,然后将其引入。

三、多用字面量语法,少用与之等价的方法

字面量数值:

NSNumber *number = @1;

字面数组:

NSArray *array = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4", nil];

字面量数组:

NSArray *array = @[@"1", @"2", @"3", @"4"];

对于字面量的话,需要注意的是,如果字面量初始化的有nil,就会报错,并且还需要注意,字面量初始化默认的是不可变的,如果需要初始化可变类型容器,就不能使用字面量进行初始化

字面量更安全

  • 通过对比可以知道字面量语法会自动抛出异常终止了程序的进行和不必要的错误,我们可以通过异常更快的发现错误

要点总结:

  • 应该使用字面量语法来创建字符串、数值、数组、字典。与创建此类对象的常规方法相比,这么做更加简明扼要。
  • 应该通过取下标操作来访问数组下标或字典中的键所对应的元素。
    用字面量语法创建数组或字典时,若值中有nil,则会抛出异常。因此,务必确保值里不含nil。

总结来说就是多用@直接创建容器和其他基本数据,而少用方法进行创建

四、多用类型常量,少用#define预处理指令

定义常量的命名

#define kString iOS
  • 在实际的开发里面,这样定义出来的常量没有类型信息,并且假设此命令在某个头文件中,那么所有引入了这个头文件的的代码,其定义的固定值都会被这个替换掉,很槽糕!

类型常量的方法:

static const NSString* iOS = @"666";

定义常量的位置方法

  • 定义常量的位置是极其重要的,我们总喜欢在头文件里声明预处理指令,那么引入了这个头文件的所有文件都会含有这个变量,万一重名,程序变得异常麻烦。
  • 所以最好不要在头文件中定义常量,不论你是如何定义常量的,因为OC中没有“名称空间”这一概念

因此我们最好在头文件中声明常量,在实现文件中定义常量
就像如下代码所写:
在这里插入图片描述

要点总结

  • 不要用预处理指令定义常量。这样定义出来的常量不含类型信息,编译器只是会在编译前据此执行查找与替换操作。即使有人重新定义了常量值,编译器也不会产生警告信息,这将导致应用程序中的常量值不一致。
  • 在实现文件中使用static const来定义“只在编译单元内可见的常量”(translation-unit-specific
    constant)。由于此类常量不在全局符号表中,所以无须为其名称加前缀。
  • 在头文件中使用extern来声明全局常量,并在相关实现文件中定义其值。这种常量要出现在全局符号表中,所以其名称应加以区隔,通常用与之相关的类名做前缀。

其实这点笔者在先前已经有总结,有兴趣的可以翻阅笔者之前的博客

五、用枚举表示状态,选项,状态码

要点总结

  • 应该用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起个易懂的名字。
  • 如果把传递给某个方法的选项表示为枚举类型,而多个选项又可同时使用,那么就将各选项值定义为2的幂,以便通过按位或操作将其组合起来。
  • 用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型。这样做可以确保枚举是用开发者所选的底层数据类型实现出来的,而不会采用编译器所选的类型。
  • 在处理枚举类型的switch语句中不要实现default分支。这样的话,加入新枚举之后,编译器就会提示开发者:switch语句并未处理所有枚举。

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Mac 上恢复永久删除的文件:有效方法

您是否错误地从 Mac 中删除了某个文件,并且确信它已经永远消失了?好吧,你可能错了。即使您认为已永久删除计算机上的数据,仍有可能将其恢复。 在本文中,您将了解如何在 Mac 上恢复永久删除的文件,并了解增…

【开源】JAVA+Vue+SpringBoot实现班级考勤管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统基础支持模块2.2 班级学生教师支持模块2.3 考勤签到管理2.4 学生请假管理 三、系统设计3.1 功能设计3.1.1 系统基础支持模块3.1.2 班级学生教师档案模块3.1.3 考勤签到管理模块3.1.4 学生请假管理模块 3.2 数据库设…

ThinkPad X201 经典小黑 折腾玩

前段时间,在折腾ThinkPad T430时,偶然看到了ThinkPad X200,一个12.1英寸的高端便携小本。 想当年,但那是总裁级别才能用的,应该是接近2万元,我们是一直用DELL的。 没想到的是,在海鲜市场上&am…

【Makefile语法 01】程序编译与执行

目录 一、编译原理概述 二、编译过程分析 三、编译动静态库 四、执行过程分析 一、编译原理概述 make: 一个GCC工具程序,它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接,然后发布必要的命令。它读出的脚本(叫做 …

Java异常的处理 try-catch-finally

目录 什么是异常通过if-else处理异常用if-else堵漏洞的缺点 try-catch例第一种处理第二种处理第三种处理第四种处理 try-catch-finally例 System.exit(0);//终止当前的虚拟机执行 什么是异常 Exception:在程序的运行过程中,发生了不正常的现象&#xff0…

【Larry】英语学习笔记语法篇——换一种方式理解词性

目录 一、换一种方式理解词性 1、名词、形容词、副词,这就是一切 2、词性之间的修饰关系 3、介词其实很简单 形容词属性的介词短语 副词属性的介词短语 ①修饰动词 ②修饰形容词 ③修饰其他副词 一、换一种方式理解词性 1、名词、形容词、副词&#xff0c…

Mysql Day03

多表设计 一对多 在多的一方添加外键约束,关联另外一方主键 一对一 任意一方添加外键约束,关联另外一方主键 多对多 建立第三张中间表,中间表至少包含两个外键,分别关联两方主键 idstu_idcourse_id 1 11 2 12313421524 案…

【Linux】构建模块

🔥博客主页:PannLZ 🎋系列专栏:《Linux系统之路》 🥊不要让自己再留有遗憾,加油吧! 文章目录 构建第一个模块1模块的makefile2内核树内构建3内核树外构建 构建第一个模块 可以在两个地方构建模…

C++——二叉树

引入 map和set特性需要先铺垫二叉搜索树,而二叉搜索树也是一种树形结构 二叉搜索树的特性了解,有助于更好的理解map和set的特性 1.二叉搜索树的概念及优缺点 1.1二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或…

网络编程-Socket套接字

目录 1.网络编程 1.1定义与图解 1.2基本概念 (1)发送端和接收端 (2)请求和响应 (3)客户端和服务端 2.Socket套接字 2.1定义 2.2分类 (1)流套接字 (2&#xff…

无人机图像识别技术研究及应用,无人机AI算法技术理论,无人机飞行控制识别算法详解

在现代科技领域中,无人机技术是一个备受瞩目的领域。随着人们对无人机应用的需求在不断增加,无人机技术也在不断发展和改进。在众多的无人机技术中,无人机图像识别技术是其中之一。 无人机图像识别技术是利用计算机视觉技术对无人机拍摄的图像…

黄金交易策略(Nerve Knife):反趋势锁定单的处理机制

锁定单是由大趋势反转之后原来的趋势单转变而来的,会在趋势再次反转时变为趋势单或者转入保留单,也有很大概率在趋势识别到转变之前就被减仓减掉了。 完整EA:Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客 一、锁定单怎么样来的&#xf…

Git分支常用指令

目录 1 git branch 2 git branch xx 3 git checkout xx 4 git checkout -b xx 5 git branch -d xx 6 git branch -D xx 7 git merge xx(含快进模式和冲突解决的讲解) 注意git-log: 1 git branch 作用:查看分支 示例: 2 git branch xx 作用&a…

[day0] 借着“ai春晚”开个场

1 文思ai笔记-新的开始 今天是2024年2月29日,也是传统农历的除夕夜。早起在ai圈看到一个比较新奇的消息,ai春晚今日举办,竟然有一点小小的激动。这些年确实好久没看过春晚了,自己对于春晚的映像还停留在“白云黑土”、“今天&…

RocketMQ客户端实现多种功能

目录 RocketMQ客户端基本流程 消息确认机制 1、消息生产端采用消息确认加多次重试的机制保证消息正常发送到RocketMQ 单向发送 同步发送 异步发送 2、消息消费者端采用状态确认机制保证消费者一定能正常处理对应的消息 3、消费者也可以自行指定起始消费位点 广播消息 …

Java多线程:`Thread`类

👑专栏内容:Java⛪个人主页:子夜的星的主页💕座右铭:前路未远,步履不停 目录 一、Thread的常见构造方法二、Thread 的常见属性三、Thread的常用方法1、start方法2、中断一个线程Ⅰ、通过共享标记Ⅱ、调用in…

大模型基础架构的变革:剖析Transformer的挑战者(下)

上一篇文章中,我们介绍了UniRepLKNet、StripedHyena、PanGu-π等有可能会替代Transformer的模型架构,这一篇文章我们将要介绍另外三个有可能会替代Transformer的模型架构,它们分别是StreamingLLM、SeTformer、Lightning Attention-2&#xff…

蓝桥杯省赛模板构建——uart

打开CubeMX 串口的发送是跟调试器放一起的,通过PA9和PA10来接收发送 选择异步通讯 波特率配置为9600 打开串口中断,因为单片机接收数据需要用到中断 生成代码 添加底层驱动代码 打开在main.h打开uart定义 uart时钟配置,由于uart是用PCLK时钟…

STM32的ADC电压采集

时间记录:2024/2/9 一、ADC相关知识点 (1)STM32的ADC时钟不要超过14MHz,不然结果的准确率将下降 (2)ADC分为规则组和注入组,规则组相当于正常运行的程序,注入组相当于中断可以打断…

飞天使-linux操作的一些技巧与知识点8-zabbix6.0 容器搭建

文章目录 安装docker安装步骤mysql下载镜像安装zabbix 使用zabbix非host模式创建 测试效果 安装docker 1. 配置官方 yum 源$ sudo yum install -y yum-utils $ sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo2. 安装 Docker$ …