Objective-C入门学习基础 类声明和定义

Objective-C入门学习基础 声明和定义是本文要介绍的内容,很详细的为友们介绍Objective-C学习基础,不多说我们先来看内容。

编译处理指令

既然Objective-C是面向对象的程序语言,所以理应支持可重用的数据和函数的封装体,即类。

是在结构体的基础上发展的产物,结构体只能处理数据,在结构体之上增加对该数据处理的函数,就构成类的概念。使程序总能提供对数据专门处理函数的安全调用,使得一系列的机能作为一个子系统供安全且重复的使用。

像结构体一样,类在使用之前必须先声明,但是Objective-C并没有像其他面向对象语言那样提供声明类的专用关键字或者语法,而是用编译处理指令来实现,特征是类声明语句都须以@符号开始。

类声明的编译处理指令以@interface开始,以@end结尾,在这之间代码便是类变量的定义和方法的声明。类的声明和定义比其他语言复杂,这会让刚开始学习Objective-C的人非常困惑(准确的说,其他语言如Java只需定义类而不用声明,而Objective-C需要先声明再定义)。

@interface 类名 : 父类名  


{  


           实例变量定义  


           ...  


}  


方法声明  


@end 

这就是Objective-C类声明的语法结构,其中实例变量是供类内部使用的变量,和结构体的成员变量相似,但是实例变量不能从类的外部使用,原则上只能被类内部的方法使用(当然只是原则上)。类可以没有实例变量,这时{}可以省略。

类的方法(注意和类方法的区别)是专属该类的方法,与普通函数的区别是:类的方法可以操作类内部的实例变量。

紧接类名后边的是父类名,也就是说可以指定类的父类,构成继承。继承使类可继承使用父类的机能,而仅定义父类没有的机能。比如父类是抽象的哺乳动物类,如果定义猫类的时候,可以继承哺乳动物这个父类,而在猫类中只定义猫区别与普通哺乳动物类的特有功能即可。

父类可以不指定,这时编译器会为类提供一个缺省的类,即根类。

Objective-C的根类随具体编译器的不同而有所不同,GCC编译器中是Object,Mac OS X的Cocoa编译环境中则是NSObject,除非自己开发根类时可以不指定父类,一般情况下都要采用系统提供的根类作为父类。仅在根类开发时,类的定义可以如下(没有父类):

@interface 类名  


{  


           实例变量声明  


           ...  


} 

类方法声明

@end 

为什么所有的类都必须继承自一个共同的根类,那是因为根类提供了类正常动作所必须的一些基本机能,比如内存的取得和释放,如果没有根类,那么所有的类都要自己去完成这些基本的工作,会使类非常的复杂而不能专注于具体业务(后面还会具体说明)。

类中实例变量的声明和普通C语言的变量声明没有什么区别,但是类方法的声明则差别很大,语法如下:

-(返回值类型)  方法名 :  临时参数列…;

首先,最左边的减号,代表该方法是类的实例方法,如果是加号则代表该方法为类方法。这里须记住一点:普通定义类的时候,方法前用减号即实例方法即可,类方法是可以不用生成实例而直接调用的方法。实例方法和类方法的区别后面会详细说明。

其次,返回值类型要放在()中,如果函数需要参数的时候,参数的类型也要放到()中,然后紧接参数名,如果有多个参数,则用逗号隔开。

C语言函数的缺省返回值类型是int型,在Objective-C中新追加了一个id型的对象类型作为缺省函数的返回值类型。虽然返回值可以不指定,但一般不建议这么做。如果没有返回值,则要用(void)做明确说明。

@interface Test : Object  


(void)method;  


@end 

在这个Test类声明中,声明了一个没有返回值,没有参数的方法method,类和方法以及变量的命名规则和C语言一样,以字母或下划线开头。但是习惯上类名的首字母大写,方法名则全部小写。

到这里,类的声明已经做好了,但是方法method只是声明了名称和类型,具体实现的代码怎么写呢?事实上,Objective-C将类的声明和定义完全分开,在类的声明中,只能定义实例变量和方法名及类型,具体的实现要用到@implementation这个编译处理指令中进行。

@implementation 类名 

实例方法定义

@end  


@implementation 

这个编译指令具体定义@interface中声明的方法,声明过的方法,必须在这里具体定义。

类的实例化

类经过声明和定义,但是还不能直接使用,使用类之前必须分配具体的内存领域且进行适当的初始化。根据类的声明具体分配一块内存,这个过程叫实例化,而具体分配的这块内存,叫做实例或者对象。

C++或者Java中为我们提供好了new运算符,可以自动由类生成实例并完成初始化,而Objective-C实例化竟然也要类自己完成(即需要类给出实例化自己的方法)。实例化需要调查生成对象的大小,申请内存完成复杂的初始化,这些任务对普通用户太难了,不过幸好编译环境为我们提供了根类(Object)来帮助完成这些功能,这也是为什么所有的类都必须继承自根类的原因(否则实例化方法要自己写)。

在根类Object中,定义了实例化根类以及继承自根类的类的类方法alloc,一般的实例方法,必须先有实例才能调用,但是类方法,没有实例也可以使用。所以类方法alloc虽然没有实例,也是可以正常调用的。鉴于alloc是用来生成实例的类方法,所以也常常也被称作工厂方法。

+alloc; 

这是Object中alloc的声明,+开头,说明是一个类方法,缺省返回值为id类型,没有参数。

id型是代表对象的广义类型,什么类型的对象都可以放入id型的对象中。

下面,就要调用alloc类方法,生成实例了,但是怎样写呢?如果熟悉C++,可能会首先想到下面的调用方式:

id obj =类名.alloc(); 

遗憾的是,这种写法是错误的,和大多数面向对象语言的调用方式不同,Objective-C有自己独特的调用方式:

[类名 类方法名:参数序列...] 

如果是调用实例方法的时候,要将类名换成实例名,其中[  ]在Objective-C中被称为消息,这是因为在Objective-C中,从对象调用方法的时候,不是直接调用,而是向对象发送特定的消息,对象接收到消息后,根据消息内容启动相应的方法,这种方式虽然带来了程序的柔软性,但是比C语言的调用方式带来额外的消耗,因为程序执行时要耗费时间检索特定的方法然后启动。

#import <stdio.h> 



#import <objc/Object.h> 



@interface Test : Object  


- (void)method;  


@end  


@implementation Test  


- (void)method {  


           printf("Kitty on your lap\n");  


}  


@end  


int main() {  



           id obj = [Test alloc];  



           [obj method];  


           return 0;  


} 

上面的程序是一个Objective-C简单但完整的类实例例子,@interface完成类的声明,继承自根类Object。@implementation完成类的定义,具体定义method的实现方法。

类声明和定义准备好之后,在main函数中,首先定义id型的对象变量obj,然后调用Test类的父类Object的方法alloc生成实例,最后调用实例obj的实例方法method,实现输出打印。

另外,如果不定义obj变量(或者说Test的实例只在这里使用一次就不用了),也可以像下面的写法:

[[Test alloc] method] 

注:像上面的程序片段一样,虽然对的声明和定义的具体位置没有要求,但是习惯上把的声明放到头文件中,的定义放到和类名同名的.m文件中。

相关推荐