iPhone开发系列文章(三)-Objective-C语言简介

本人翻译的Apple Dev Center的技术资料并稍作修改。

转载请注明出处:http://blog.csdn.net/zhyzh2046/

学习Objective-C:初级读本
Objective-C是一种简单的计算机语言,支持复杂南通的面向对象编程。Objective-C从标准的ANSI C语言扩展而来,并提供了定义类、方法和属性的语法,还有其它结构来促进类的动态扩展。类的语法和设计把部分基于第一种面向对象的编程语言Smalltalk。
如果你有使用面向对象语言的经验,接下来的信息会帮你学习到Objective-C基本的语法。许多传统的面向对象概念,如封装、继承和多态,都会在Objective-C中出现。但是会存在一些重要的不同之处,不过这篇文章会讲解这些不同,而且还可以查到更加详细的信息。
如果你从来没有使用过面向对象语言,在开始之前,至少需要基本理解相关的概念。对象和面向对象结构的使用是设计iPhone程序的基础,而且理解它们是怎样交互的是创建程序的必要条件。 使用 Objective-C 进行面向对象编程中介绍了面向对象概念概述。
要了解关于Objective-C更加详细的信息和语法,请查阅Objective-C程序设计。

Objective-C:C语言的超集

Objective-C是C语言的ANSI版本的超集,支持相同的基础语法。与C语言相同,Objective-C也会定义头文件和源文件,将公共的声明和实现分离。Objective-C头文件使用的文件扩展名列在表1中。 

 

表1 Objective-C源代码的文件扩展名
扩展名代码类型
.h头文件。头文件中包含类、类型、函数和常量的声明。
.m源文件。这是源文件的一种典型扩展,可以包含C代码和Objective-C代码。
.mm源文件。这种源文件除了可以包含C代码和Objective-C代码之外,还可以包含C++代码。这种扩展名只能用于你实际引用了C++的类,或者引用了Objective-C的功能。

 

当需要在头文件包含头文件时,可以使用标准的#include预编译指令,但是Objective-C提供了更好的方法。#import指令和#include指令是一样的,除了它能保证相同的文件永远不会被引用多次。Objective-C的示例和文档都建议使用#import,你自己的代码也应该如此。

Strings

作为C的超集,Objective-C在指定字符串时,具有和C一样的约定。换句话说,单个字符使用单引号,字符串会使用双引号包围。但是,大多数Objective-C框架经常不使用C样式的字符串。取而代之,大多数框架将字符串封装在一个NSString对象中。

NSString类是字符串的对象载体,它具有希望的所有优点,包括为处理任意长度的字符串内置的内存管理、支持Unicode、Printf风格的格式化优点等等。但由于一些字符串经常使用,Objective-C提供了一个速记符号从常量创建NSString对象。使用这用速记,你所要做的仅仅是在一个正常的双引号包含的字符串之前加上一个@符号,如下示例: 

NSString *  myString  =   @" My String  "
NSString
*  anotherString  =  [NSString stringWithFormat: @" %d %s " 1 @" String " ]; 

//  Create an Objective-C string from a C string 
// 从C字符串创建Objective-C字符串 
NSString *  fromCString  =  [NSString stringWithCString: " A C string "  encoding:NSASCIIStringEncoding]; 

Classes 


正如大部分其它面向对象语言一样,Objective-C中的类是一个基本的结构体,封装了一些数据以及操作这些数据的动作。对象是类运行时的实例,包含类中声明的成员变量和类方法的指针在内存中的拷贝。

Objective-C中创建一个类需要截然不同的两个部分:接口和实现。接口部分包含类的声明,还会定义成员变量和与类相关联的方法。实现部分包含类方法的实际实现代码。图1显示了声明一个叫做MyClass的类的语法,它继承了NSObject基类。类声明会以@interface预编译指令开始,以@end指令结束。类名之后(有一个冒号分开)是父类的名称。类的成员变量在大括号包含的代码中声明({和})。在成员变量之后的代码块是类声明的方法列表。每个成员变量和方法的声明之后都要以分号结尾。 
图1 类的声明


图2显示了上例中MyClass的实现。像类的声明一样,类的实现由两个预编译指令来指示-在这里是@implementation和@end。这些指令定义了范围信息,告诉编译器需要将附上的方法和相关的类联系起来。因此,方法的定义与接口中声明的要匹配,除了代码块的包含。

图2 类的实现

注意:尽管上述例子中,类的声明部分只声明了一些方法,类是可以在这里声明属性的。关于属性的更多信息,请看“属性”一节。

当使用变量存储对象时,经常会使用指针类型。Objective-C中,强类型和弱类型变量都可以保存对象。强类型指针的变量在声明时必须包含类名。集合类经常使用弱类型指针,因为可能还不知道集合中对象的类型。如果你习惯于使用强类型的编程语言,你可能会认为弱类型变量的使用会产生问题,但是实际上,在使用Objective-C编程时,它会带来极大的便利,同时会带来更好的扩展性。

下面这个例子演示了MyClass类的强类型和弱类型变量的声明:

MyClass *  myObject1;  //  强类型
id myObject2;  // 弱类型

Methods 
方法
 

  

Objective-C 语言中的类可以声明两种方法:实例方法和类方法。实例方法的执行者必须是类的一个特定实例。换句话说,在调用实例方法之前,必须先创建一个类的实例,之后必须使用这个实例来调用实际的方法。相比之下,类方法不需要创建类的实例,后面会有详细的解释。

  

方法的声明由方法类型标识符、返回类型、一个或多个署名关键字和参数的名称、类型信息组成。图 3 中声明了一个 insertObject:atIndex: 的实例方法。方法声明的前面加上了一个减法符号(-),这说明这个方法是一个实例方法。方法的实际名称(insertObject:atIndex:)是所有署名关键字串联起来的,包括冒号字符。冒号说明参数的存在。如果方法没有参数,第一个(唯一的)署名关键之后可以忽略冒号。这个例子中,方法含有两个参数。
图3  声明方法的语法
当调用一个方法时,要通过"messaging”来通知相应的对象。这个例子中的消息就是方法名和这个方法所需的参数信息。发送到对象的所有消息是动态发送的,因此这有利于Objective-C的多态特征。换句话说,如果子类定义了与父类同名的方法,子类会第一个收到消息,然后可以选择是否要将这个消息转交给它的父类。
 
消息都是放在方括号 ([ ]) 中。在方括号中,收消息的对象放在左边,消息 ( 和任何消息需要的参数 ) 放在右边。例如,发送 insertObject:atIndex: 消息给myArray对象,使用的语法如下:
[myArray insertObject:anObj atIndex: 0 ];
为避免声明大量局部变量来存储临时数据, Objective-C 支持嵌套消息。每一个嵌套消息的返回值都可以作为另一个消息的参数或者是目标。例如,上例中的任何变量都可以被替换成能得到值的消息。因此,如果有另外一个对象 myAppObject ,它的方法方法可以访问数组对象,并且有另外一个数组对象,可以将上面的例子写出如下样子:
[[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] atIndex: 0 ];
尽管前面的例子是向一个类的实例发送消息,还可以向类本身发送消息。当向类发送消息时,调用的方法必须定义成类方法而不是实例方法。可以这样认为:类方法同 C++ 语言中类的静态成员方法有些相似(但又不是完全相似)。
类方法有代表性的用法有,作为工厂方法来创建类的一个新实例,或者用来访问与类相关的一些共享信息。类方法的定义语法与实例方法是完全一样的,只有一点不同。类方法使用加法符号(+),而不是减法符号作为方法的类型标识符。
下面的例子演示了类方法的使用,这里它作为类的工厂方法。在这里,arrayWithCapacity:方法是类NSMutableArray的类方法,他会申请并初始化一个新的类实例并返回它。
NSMutableArray *    myArray  =  nil;     //  nil 本质上与NULL相同

// 创建新的数组并赋值给myArray变量
myArray  =  [NSMutableArray arrayWithCapacity: 0 ];

 

Properties
属性
属性是一种便利符号,用来代替存取方法(accessor methods)。属性并不是在类的声明中创建一个新的成员变量。他们仅仅为定义用来访问已经存在的变量的方法指定的快捷方式。类可以使用属性标记来公开成员变量,而不是使用getter和setter方法。类还可以使用属性来公开“virtual”(虚)的成员变量—它是动态计算的一部分数据并且并不实际存储在成员变量中。
 
实际点说,属性的使用减少了你的冗余代码量。应为大部分存取方法用相似的方式实现,使用属性可以不必为每一个成员变量提供截然不同的 getter setter 方法。相反,你可以使用属性的声明指定具体的动作,在编译的时,会根据声明合成实际的 getter setter 方法。
 
因为属性的声明会创建实际的方法,可以和方法的声明一起定义在类的接口中。基本的定义使用 @property 预编译指令,后边是属性的类型信息和名称。可以使用定制选项配置属性,它定义了存取方法有怎样的行为。下面的例子显示了一些简单的类型声明:
@property BOOL flag;
@property (copy) NSString
*  nameObject;   //  赋值过程中拷贝对象
@property ( readonly ) UIView *  rootView;   //  仅创建getter方法
 
属性的另一个好处是在代码中可以使用点语法来访问他们,如下演示:
 myObject.flag  =  YES;
 CGRect   viewFrame 
=  myObject.rootView.frame;
 
尽管上面的例子中的对象和属性的名字很做作,但是他们演示了属性的灵活性。点语法实际上屏蔽了相关一系列方法的调用。每个可读属性由同名的方法支持。每个可写属性由附加的方法 set PropertyName : 支持,在这里属性名称的第一个字母大写了。 ( 这些方法是属性的实际实现,同时也是可以在没有成员变量支持的类中包含属性定义的原因。 ) 不用属性去实现上面代码完成的功能,你需要编写如下代码:
 [myObject setFlag:YES];
 CGRect   viewFrame 
=  [[myObject rootView] frame];
 
关于在类中如何声明属性的更多信息,请查阅 Objective-C 程序设计中 属性 一节。
 
Protocols and Delegates
协议和代理
 
协议声明的方法可以被任何一个类实现。协议不是类本身。他们仅定义了其它对象有责任实现的接口。当在自己的类中实现协议的方法时,你的类就是遵守这个协议的。
 
iPhone OS 中,协议经常被用作实现代理对象。代理对象是一个能代表其它对象或与其它对象合作的一个对象。学习协议、代理和其它对象相互影响的最好方法就是从例子中学习。
 
UIApplication 类实现了应用程序所需的功能。不是强制继承UIApplication类来接收一个简单的应用程序当前状态的通知,而是UIApplication类调用赋值给代理对象的方法来分发这些通知。实现了UIApplicationDelegate协议方法的对象可以接收这些通知并提供合适的响应。
 
协议的声明类似于类接口的声明,有一点不同的是,协议没有父类,并且不能定义成员变量。下面的例子演示了只有一个方法的协议的声明:
@protocol MyProtocol
-  ( void )myProtocolMethod;
@end

 

很多代理协议中,采用协议只是大概实现了协议中定义的方法。一些协议需要明确声明支持的协议,但是现在假设仅实现方法就足够了。但是,如果想将更多的只是应用到你的开发中,你应该多花些时间来学习协议和他们的使用方法,可以通过查阅 Objective-C 程序设计中的 协议 一节。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值