您的位置:华清远见教育科技集团 >> iOS资料 >> iOS开发入门:Objective-C基础语法(三)  
 
iOS开发入门:Objective-C基础语法(三)
分享到:

协议和范畴类

协议可以用来声明能够在任何类中实现的方法,甚至那些实现该方法的类继承自别的类。协议方法定义的行为是独立于任何一个类的。协议可以定义一个要求其他类必须承诺实现的接口。也就是说,如果你的类实现了协议中的方法,那么这个类就承诺要完成该协议。

从实用的角度说来,协议定义了一系列方法,并建立起对象之间的“合约”。而这些对象不必是任何一个确定的类的实例。这个合约使得对象之间可以进行交流。某个对象想要告诉另一个对象,马上将要面临的事件,或者想要询问关于那些事件的建议。

UIApplication 类实现了所需的应用行为。你不必为了接收简单的应用当前状态的消息而创建一个 UIApplication 的子类。UIApplication 类会调用指定的委托对象中的特定方法来传递那些消息。实现了 UIApplicationDelegate 协议方法的对象就能够接收到那些消息了,并且能够提供合适的反馈。

在承诺实现、或采用某个协议的接口代码中,协议的名称要写在父类名称后边的一对尖括号里(<…>)。在“你的第一个 iOS 应用”教程里,你采用了 UITextFieldDelegate 协议:

@interface HelloWorldViewController : UIViewController {
}
@end

在实现中,你无需声明协议方法。

协议的声明看起来和类接口很相似,不过不同的是协议没有父类,并且不含任何实例变量(但它们能够声明属性)。下面的例子展示如何声明只有一个方法的简单协议:

@protocol MyProtocol
    - (void)myProtocolMethod;
    @end

对于许多委托协议而言,采用一个协议就等于是实现该协议中定义的方法。有些协议要求你明确声明你会支持该协议,而有些协议则是既包含必须实现的方法,也包含可选方法。

当你在 Objective-C 框架中浏览头文件时,你很快就会看到类似这样的语句:

@interface NSDate (NSDateCreation)

这行语句声明了一个范畴类(category),其语法是将范畴类的名称包裹在一对圆括号中。范畴类是 Objective-C 语言的一个特性,让你能够扩展某个类的接口,而无需创建它的子类。范畴类中的方法将成为此类的一部分(在你的程序作用域范围内),并会被此类的所有子类继承。你可以向此类(或它的子类)的任意一个实例发送消息来调用范畴类中声明的方法。

你可以利用范畴类在一个头文件里组织互相关联的方法声明。你甚至可以在不同的头文件中放入不同的范畴类声明。Cocoa Touch 框架和 Cocoa 框架在几乎所有头文件中都利用了这个技术,代码才如此明晰。你还能使用匿名范畴类(也就是在圆括号中不写任何字符),这样可以把实例变量隐藏在私有的实现文件里。

预定义类型和编码策略

在 Objective-C 语言中有一些特定的词汇,你要避免在声明变量时使用这些词汇,因为它们都有专门的用途。其中有一些是编译器指令,以 @ 符号开头(例如 @interface @end)。有些保留词汇是预定义类型,以及和这些类型有关的文字。Objective-C 使用一系列不属于 ANSI C 的预定义类型和词汇。在某些情况下,这些类型和词汇会代替它们在 ANSI C 中的对应者。下表列出了几个非常重要的类型,包括每个类型所允许的词汇。

类型、描述和词汇:

id – 动态对象类型。动态类型和静态类型对象的否定词汇为 nil
    Class – 动态类的类型。它的否定词汇为 Nil
    SEL – 选择器的数据类型(typedef);这种数据类型代表运行时的一种签名方法。它的否定词汇为 NULL
    BOOL – 布尔型。代表它的值的词汇为 YESNO

你通常会在代码排错以及流程控制中使用这些预定义的类型和词汇。在程序的流程控制语句中,你可以通过检测特定词汇来判断如何采取下一步动作。例如:

NSDate *dateOfHire = [employee dateOfHire];
    if (dateOfHire != nil) {
        // 处理此种情况
    }

把代码解释一下:如果对象代表的聘用日期不为 nil,也就是说是一个合法的对象,那么逻辑就朝一个特定的方向发展。下边是这段代码的简化版,效果是相同的:

NSDate *dateOfHire = [employee dateOfHire];
    if (dateOfHire) {
        // 处理此种情况
    }      

你甚至可以把代码简化成这个样子(前提是你不需要引用 dateOfHire 对象):

if ([employee dateOfHire]) {
        // 处理此种情况
    }

处理布尔值的方法是一样的。在这个例子中,isEqual: 方法会返回一个布尔型的值:

BOOL equal = [objectA isEqual:objectB];
    if (equal == YES) {
        // 处理此种情况
    }

你同样可以按照前边省略 nil 的方式来简化这段代码。

在 Objective-C 语言里,你可以对 nil 发送消息,不必担心任何副作用。其实,是根本不会有任何作用,只不过运行时会返回 nil,如果方法本来要返回一个对象的话。发送给 nil 的消息返回的值只要是一个对象,代码就能继续正常工作。

另外两个重要的预留词汇是 selfsuper。前者 self 是个局部变量,你可以在消息实现中把它看做当前对象进行引用;它和 C++ 语言中的 this 是一样的。你可以用预留词汇 super 替换 self,但只能作为消息表达式的接收者。如果你对 self 发送了消息,那么运行时首先就会在这个对象的类中寻找相应的方法实现;如果这里找不到,那么它会转而到其父类中去查找(如此往复)。如果你对 super 发送消息,运行时首先就是去父类中寻找方法的实现。

利用 self super 主要是为了发送消息。当被调用的方法在 self 的类中被实现之后,你就可以向 self 发送消息,例如:

[self doSomeWork];

self 还可以用在点语法中,用来调用由已声明的属性生成的存取方法,例如:

NSString *theName = self.name;

你常常会在重载(既重新实现已有的方法)从父类继承而来的方法时向 super 发送消息。在这种情况下,被调用的方法拥有和重载后方法相同的签名。

 更多相关文章

·iOS开发入门:Objective-C基础语法(二)
·iOS开发入门:Objective-C基础语法(二)
·iOS开发入门:Objective-C基础语法串讲
·iOS开发入门:Objective-C语言简介
·iOS 应用程序开发教程:十、排除故障和检查代码