ObjC的语法主要基于smalltalk进行设计的,除了提供常规的面向对象特性外,还增加了很多其他特性,这一节将重点介绍ObjC中一些常用的语法特性。当然这些内容虽然和其他高级语言命名不一样,但是我们都可以在其中找到他们的影子,在文章中我也会对比其他语言进行介绍,这一节的重点内容如下:
协议protocol
在ObjC中使用@protocol定义一组方法规范,实现此协议的类必须实现对应的方法。熟悉面向对象的童鞋都知道接口本身是对象行为描述的协议规范。也就是说在ObjC中@protocol和其他语言的接口定义是类似的,只是在ObjC中interface关键字已经用于定义类了,因此它不会再像C#、Java中使用interface定义接口了。
假设我们定义了一个动物的协议AnimalDelegate,人员Person这个类需要实现这个协议,请看下面的代码:
AnimalDelegate.h
// // AnimalDelegate.h // Protocol&Block&Category // // Created by Kenshin Cui on 14-2-2. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // //定义一个协议 @protocol AnimalDelegate <NSObject> @required //必须实现的方法 -(void)eat; @optional //可选实现的方法 -(void)run; -(void)say; -(void)sleep; @end
Person.h
// // Person.h // Protocol&Block&Category // // Created by Kenshin Cui on 14-2-2. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import <Foundation/Foundation.h> #import "AnimalDelegate.h" @interface Person : NSObject<AnimalDelegate> -(void)eat; @end
Person.m
// // Person.m // Protocol&Block&Category // // Created by Kenshin Cui on 14-2-2. // Copyright (c) 2014年 Kenshin Cui. All rights reserved. // #import "Person.h" @implementation Person -(void)eat{ NSLog(@"eating..."); } @end
这里需要说明几点:
- 一个协议可以扩展自另一个协议,例如上面AnimalDelegate就扩展自NSObject,如果需要扩展多个协议中间使用逗号分隔;
- 和其他高级语言中接口不同的是协议中定义的方法不一定是必须实现的,我们可以通过关键字进行@required和@optional进行设置,如果不设置则默认是@required(注意ObjC是弱语法,即使不实现必选方法编译运行也不会报错);
- 协议通过<>进行实现,一个类可以同时实现多个协议,中间通过逗号分隔;
- 协议的实现只能在类的声明上,不能放到类的实现上(也就是说必须写成@interface Person:NSObject<AnimalDelegate>而不能写成@implementation Person<AnimalDelegate>);
- 协议中不能定义属性、成员变量等,只能定义方法;
事实上在ObjC中协议的更多作用是用于约束一个类必须实现某些方法,而从面向对象的角度而言这个类跟接口并不一定存在某种自然关系,可能是两个完全不同意义上的事物,这种模式我们称之为代理模式(Delegation)。在Cocoa框架中大量采用这种模式实现数据和UI的分离,而且基本上所有的协议都是以Delegate结尾。
现在假设需要设计一个按钮,我们知道按钮都是需要点击的,在其他语言中通常会引入事件机制,只要使用者订阅了点击事件,那么点击的时候就会触发执行这个事件(这是对象之间解耦的一种方式: