Objective-C 2.0从2006年正式发布至今已经有10年了。Apple在此期间也不断地为其注入新的语法特性,比如Blocks、NSNumber literal、NSArray literal、NSDictionary literal、@() compund literal、Object subscripting、instancetype、lightweight generics等等。然而,其核心语法变化不大。

本人从2009年夏季开始接触Objective-C,一开始总是不习惯其[object   message]这种语法形式,不过随着Xcode自身智能感知的不断加强,编辑也逐步方便,所以也渐渐地习惯了,呵呵~现在用下来,感觉Objective-C在面向对象编程方面有其独到之处,而且灵活性相当大,编译器负担也很小,增加的仅仅是运行时库。不过相对于Java这种需要虚拟机的运行时来说要小得多。因此,它是对C++与Java的折衷。C++太过依赖编译器,Java的运行时太过庞杂,而且这两种编程语言对于类型的限制太过重,导致原本一些本应该十分灵活强大的语法特性也受到很多制约。所以,本人也时常跟朋友、同事之间开玩笑地说,“用C++来做项目,总是先考虑其各种语法糖以及各种坑,而往往不能开门见山地进行软件设计”。而Java新增的很多语法也是比较鸡肋,比如泛型就是其中之一,还有Java 8所引入的Lambda表达式。这货跟Java 1.4所引入的匿名类对象没太大不同,反而是Method Reference更有用些,呼呼~

当然,Objective-C也不能说完全没有缺陷,下面我就谈谈目前Objective-C比较令人不快的特性以及其改进建议以及新增若干语法特性。

1、消息发送机制

一开始,Brad Cox引入[object  message]的机制确实不错,这个对已有的C语言语法没有任何冲突,因此Objective-C至今对于C/C++的兼容性都能做到100%。不过,这种写法对于编写代码来说有个很大的弊端——当嵌套的方法调用过多时,由于需要往前加[,因此,对于使用不带智能感知的编辑器来说就相当讨厌了。比如:

NSString *str = [[[NSString alloc] initWithFormat:@"%d", 100] autorelease];

上述代码嵌套了多层方法调用。但是对于程序员来说,写代码时都是按照线性思维进行的。也就是说,我一开始总是会想到先分配一个NSString对象,然后调用init初始化方法对其初始化,最后想到用autorelease方法来省去后面手工release的麻烦。而用[]机制,那么你每写好一个方法调用就需要回过去加[,这显然十分麻烦~

而本人这里所提供的改进意见是,使用 . 这个操作符(operator)来表示消息发送机制:

object . message (parameter-list)

上述代码可写为:

NSString *str = NSString.alloc().initWithFormat(@"%d", ).autorelease();

整个调用过程就显得更为清晰。而之前方法的声明与定义形式依旧不变,所以,如果方法里有多于1个形参,那么后续形参也需要带有自己的标签。比如:

    NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *path = [[fileMgr URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:NULL] path];
NSLog(@"The path is: %@", path); // 可写为以下形式:
NSFileManager *fileMgr = NSFileManager.defaultManager();
NSString *path = fileMgr.URLForDirectory(NSCachesDirectory, inDomain:NSUserDomainMask, appropriateForURL:nil, create:NO, error:NULL).path();

这看上去与Swift的方法调用差不多。

那么现在估计各位可能会有这么一个问题,使用了点语法作为消息发送(方法调用)之后,如何与property加以区分呢?

如果 . 操作符后面的标识符后面没有圆括号,说明使用的是property,如果带有括号,说明使用的是方法。比如:

NSUInteger len = @"Hello".length;    // 这里使用的是property

NSUInteger len = @"Hello".length();  // 这里显式地调用property的getter方法,相当于[@"Hello" length]

此外,由于Objective-C已经有了强大灵活的消息机制,所以它不需要再包含类似于C++中指向类成员函数指针这种特性,所以用点语法其实完全能行得通,而且也能与现有的C/C++的语法完全兼容。

2、类静态成员变量与类property:

我们知道,现在Objective-C类有类方法,但是木有类属性。其实,加入类成员变量和类属性不仅能使得Objective-C在语法体系上更加完备,而且也能提供更好的模块化编程形式。

类静态成员变量非常简单,只需要在@interface或@implementation的 { }作用域中使用static存储类说明符即可。比如:

@interface MyObject : NSObject
{
@public int n; // 对象成员变量 static int s; // 类静态成员变量
} @end

对类静态成员变量的访问也是通过 -> 操作符。比如:

MyObject *obj = MyObject().alloc().init();
int a = obj->n; // 访问对象成员
a += MyObject->s; // 访问类静态成员

而要定义类property的方法也同样简单,跟定义对象property一样,只是在前面添加 + 号。比如:

@interface MyObject : NSObject
{
@public int n; // 对象成员变量 static int s; // 类静态成员变量
} - @property (nonatomic, retain) NSString *objStr; // 定义了对象property
+ @property (nonatomic, retain) NSString *classStr; // 定义了类property @end

在synthesize的时候,对象property与类property需要分开。在做类property的synthesize的时候,前面也是加 + 号进行指定。比如:

@implementation MyObject

- @synthesize objStr;      // 综合对象property
+ @synthesize classStr; // 综合类property @end

这么做可以使得对象property与类property可以有完全相同的属性名。上述代码片段中,@synthesize objStr相当于编译器给MyObject类定义了 - (void)setObjStr:(NSString*, retain)str与- (NSString*)objStr这一对setter和getter方法,同时为MyObject增添了私有对象成员变量NSString*objStr。而@synthesize classStr相当于编译器给MyObject类自动定义了+ (void)setClassStr:(NSString*, retain)str与+ (NSString*)classStr这一对setter和getter方法,同时为MyObject增添了私有类静态成员变量NSString *classStr。

这里要再提的一点是,引入了类静态property之后,实例property可以在@property前加 - 号,@synthesize之前也可加 - 号。否则对于某些星座的人来说,看代码没对齐难受得慌,呼哈哈~如果 - 缺省,那么默认为实例property。

下面我简单介绍一下类静态成员变量与类属性的实现方式。因为Objective-C完全基于C语言,可以看作是C语言的一套马甲~所以我们完全可以把Objective-C代码的编译过程理解为先将源代码完全翻译成C代码,然后再对C代码进行编译。所以,这里对于新增语法的特性也不能违背此重要原则。对于Objective-C编译器如果遇到了类静态成员以及/或类属性,那么可以把此类定义为一个全局外部对象,对象名可以诸如_objc_class_<class name>_<category name>。然后,runtime库也需要增加对类属性的访问接口。

3、带方法形式说明的SEL类型

我们在使用Objective-C时,常常会发现SEL类型参数没有具体说明,此时我们就可能需要进一步查找各种文档资料确定这个selector传多少个参数,每个参数需要是什么类型的。在Objective-C 3.0中,我们将给SEL加上方法类型说明,包括方法的返回类型以及参数类型。比如,我们常用的用于定时器消息回调的参数可以写作为:

SEL<void* (NSTimer*)>

这里之所以使用<>是因为,一来这样可以跟函数参数的圆括号进行明显区分开;二来这种表达更类似protocol,表示这个selector实参需要满足<>内的返回类型与参数列表形式。

以上就是我目前所想到的内容。各位感觉何如呢?呼呼~

漫谈Objective-C在语法上的改进的更多相关文章

  1. C++与Java语法上的不同

    最近学习算法和刷题基本都是用C++写的程序,在这个过程中,发现C++和Java在语法上有很多相同点,但也有很多不同点,而这些不同点对于已经掌握Java的程序员来说,理解C++代码可能会有些吃力甚至困难 ...

  2. 语法上的小trick

    语法上的小trick 构造函数 虽然不写构造函数也是可以的,但是可能会开翻车,所以还是写上吧.: 提供三种写法: ​ 使用的时候只用: 注意,这里的A[i]=gg(3,3,3)的"gg&qu ...

  3. swift 2.2 语法 (上)

    前言: 1.此文中的语法会根据Swift的升级变动而更新. 2.如果需要请移步 -> swift2.2 语法(中).swift 2.2语法(下) Swift与OC中常见的区别 导入框架 OC: ...

  4. 12天搞定Python,基础语法(上)

    不知你是否见过建楼房的过程,没有的话,找个时间去瞧一瞧,看一看.看过之后,你就会明白.建楼房,只有打好地基之后,才能在砌墙,建的楼层越高,打的地基就越深. 学编程也一样,要想得心应手的应用,得先打好地 ...

  5. Markdown基础语法(上)

    前言 按照官方文档,和根据自己所用和所理解所写 一.标题语法 一级标题最大,六级标题最小 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标 ...

  6. Java 和C/C++的“语法”上的差异!

    额其实认为语言语法之间是没有可比性的! 但是因为额曾经学过C/C++,而今又学Java,有赵本山说的话:“知识都学杂了!”,所以我个人总结一下,望提醒自己! Java C++ double 要用%f: ...

  7. 吾八哥学Python(三):了解Python基础语法(上)

    学习一门开发语言首先当然是要熟悉它的语法了,Python的语法还算是比较简单的,这里从基础的开始了解一下. 标识符1.第一个字符必须是字母表中字母或下划线'_'.2.标识符的其他的部分有字母.数字和下 ...

  8. 第2章 Java基本语法(上): 变量与运算符

    2-1 关键字与保留字 关键字(keyword) 保留字(reserved word) 2-2 标识符(Identifier) 案例 class Test{ public static void ma ...

  9. Java基础语法(上)

    Java编译报错出现非法字符,原因是存在中文字符. Java关键字的字母都是小写. Java是一种强类型语言,针对每一种数据都给出了明确的数据类型. 数据类型分类: A:基本数据类型 B:引用数据类型 ...

随机推荐

  1. C++语法备忘

    记录一些C++的语法方便日后查看. 1.C++初始化语法 C++中新增加了两种初始化语法,其中大括号初始化器需要C++11以上的实现,使用时可以加等号,也可以不加,而且大括号中可以不包含任何东西,这种 ...

  2. TCP、Http和Socket 优劣比较

    转自:http://www.cnblogs.com/webwlsong/p/3198712.html 了解HTTP和Socket之前先对网络7层协议有个了解: 7 应用层6 表示层5 会话层 4 传输 ...

  3. Python3+Appium学习笔记07-元素定位工具UI Automator Viewer

    这篇主要说下如何使用UI Automator Viewer这个工具来定位元素.这个工具是sdk自带的.在sdk安装目录Tools目录下找到uiautomatorviewer.bat并启动它 ​ 如果启 ...

  4. ocr 识别 字体大小问题?

    字体大 字体小?????? ???????????

  5. 微信PC版Hook研究思维导图

  6. 使用 webpack-bundle-analyzer 分析 webpack 代码库拆分块

    github:https://github.com/webpack-contrib/webpack-bundle-analyzer 1.安装: cnpm install webpack-bundle- ...

  7. Web应用中的缓存一致性问题

    上篇总结了缓存中出现频率比较高的一些问题,今天详细说说web应用中的缓存一致性问题. 主要说以下三个方面 数据库与缓存中数据不一致出现的情形 发生不一致时的优化思路 如何保证数据库与缓存的一致性 先来 ...

  8. Linux使用帮助详解

    主要内容:                    whatis                    command --help                     man and info   ...

  9. FineAdmin.Mvc 使用ok-admin+ASP.NET MVC搭建的通用权限后台管理系统

    FineAdmin.Mvc 介绍 使用ok-admin+ASP.NET MVC搭建的通用权限后台管理系统RightControl后台layui模板不太好看,换成ok-admin v2.0重写一遍.项目 ...

  10. [codeforces][dp]

    链接:https://ac.nowcoder.com/acm/problem/21314来源:牛客网 题目描述 牛牛正在打一场CF 比赛时间为T分钟,有N道题,可以在比赛时间内的任意时间提交代码 第i ...