详解Objective-C学习笔记之面向对象编程

Objective-C学习笔记之面向对象编程是本文要介绍的内容,主要详细的介绍了面向对象编程的内容,对于资深的C++程序员来说,面向对象编程不是什么新鲜的概念,类、对象、实例、方法这些概念就不再冗述了。和上一篇 Objective-C学习中对 C语言的扩展一样,这篇主要侧重于Objective-C中的OOP,有哪些与我们熟识的C++不同的概念。

Point : NSObject  


{  


  int X;  


  int Y;  


}  


- (void) SetX: (int) X;  


- (void) SetY: (int) Y;  


- (void) Show;  


// Point 

下面进行逐句分析。

“Point”告诉编译器:“这是为名为Point的新类定义的接口。”,而后面的“NSObject”告诉编译器,Point类是基于 NSObject类的。该语句表明每个Point类都是一个NSObject,并且每个Point都将继承NSObject类定义的所有行为。

花括号中的内容是用于大量创建新Point对象的模板。它表明,创建新Point对象时,该对象由两个元素构成——X和Y,每个创建出来的Point类对象都将拥有自己的X和Y。

随后的代码看起来像是C函数原型,在Objective-C中,它们称为方法声明。方法声明指出每种方法的名称、方法返回值的类型和某些参数。

前面的短线“-”表明这是Objective-C方法的声明,这是一种区分函数原型与方法声明的方式。

短线后面是方法的返回类型,位于圆括号中,void表示无返回值。Objective-C方法可以返回与C函数相同的类型:标准类型(整型、浮点型和字符型)、指针、对象引用和结构。

方法类型之后是方法名称,如果方法使用参数,在名称的结尾处需要使用冒号。这个冒号是名称的一部分,它告诉编译器后面会出现参数。

参数的类型是在圆括号中指定的,紧随其后的是参数名称。

最后的“Point

- (void) SetX: (int) thisX  


{  



  X = thisX;  



} // SetX  


 


- (void) SetY: (int) thisY  


{  



  X = thisY;  



} // SetY  


 


- (void) Show  


{  


  NSLog(Point at (%d, %d)", X, Y);  


} // Show  


// Point 

下面进行逐句分析。

@implementation是一个编译器指令,表明它将为某个类提供代码。类名(Point)出现在@implementation之后,该行的结尾处没有分号。

接下来是各个方法的定义,它们不必按照在@interface指令中的顺序出现。你甚至可以在@implementation中定义那些在@interface中无相应声明的方法。可以把它们看成是私有方法,仅在类的实现中使用。

方法定义中的第一行看上去与@interface部分的声明非常类似,二者间的主要差别就是结尾处没有分号,另外还需要注意到我们将方法的参数重新命名了,@interface部分的方法声明中使用了名称X和Y,是为了确切告诉读者参数的用处。在具体实现中,我们必须区分参数名称和实例变量名称,所以需要将参数重命名。

SetX方法和SetY方法的结构几乎一样,对于Show方法需要注意,方法名的结尾处没有冒号,说明它不使用任何参数。

最后的“@end”代码告诉编译器,我们已经完成了Point类的实现。

实例化对象

实例化对象就是根据我们前面写好的声明创建一个新对象。为了创建新的对象,我们先来熟悉一个新的操作符——“[]”操作符。

在C语言中,程序员使用方括号引用数组元素。而在Objective-C中,方括号还有其他意义:它们用于向某个对象发送消息,通知其执行某种操作。在在方括号内,第一项是对象,其余部分是你需要发送的消息。例句如下:

[Point new] 

Objective-C具有一个极好的特性,你可以把类当成对象来向类发送消息。在本例中,我们就是向Point类发送new消息,通知Point类创建一个新对象。以下是完整的实例化对象代码。

int main (int argc, const char* argv[]){  id thisPoint;  



   thisPoint = [Point new];   



    [thisPoint SetX: 0];   


     [thisPoint SetY: 0];     


     [thisPoint Show];  


 }    


// main 

下面进行逐句分析。

这个main()函数和普通C程序中的main()函数没有什么区别,参数argc保存启动参数的数量,因为程序名常用作启动参数传递,所以argc通常为1或更大。参数argv数组用于保存启动参数,argv[0]通常就是程序名,如果有其他启动参数,依次存放在argv[1]、argv[2]等等。

id代表identifier,是一种泛型,用于表示任何种类的对象。实际上,id就是指向某个对象的指针。

通过给Point类发送new消息,创建了一个Point类的实例,thisPoint中保存的就是指向这个市里的指针。

接下来就是通过给thisPoint对象发送SetX和SetY消息来设定其元素X和Y。需要注意到,和方法声明中类似,[]操作符发送给对象的消息需要携带参数时,在消息之后需要使用冒号,而携带的参数就跟随在冒号的后面。

最后就是通过给thisPoint对象发送Show消息显示其相关信息。同样需要注意,当发送的消息没有参数时,后面千万不可使用冒号。

继承

编写面向对象的程序时,你所创建的类和对象之间存在一定的关系。它们协同工作才能实现程序相应的功能。处理类和对象间的关系时,OOP有个很重要的特性叫做继承,使用继承可以定义一个具有原有类所有功能的新类。

在前文的@interface部分声明新类的时候,其实已经用到了继承的语法。

@interface Point : NSObject  

如上例中所示,冒号后的标识符就是需要继承的类。在Objective-C中,可以从非类中继承对象,但如果使用Cocoa,会希望从NSObject继承对象,因为NSObject提供了大量有用的特性。@interface部分最简单的继承代码可以如下所示:

@interface MyPoint : Point@end  // MyPoint 

这时,MyPoint类就继承了Point类的所有数据成员和方法。在下面的文字中,我们统一用超类来描述所继承的类,用子类来描述实施继承的类。这里Point就是MyPoint的超类,而MyPoint就是Point的子类。

我们在写新的子类时,有时为了在类中引入某个独特的特性,需要添加新方法。还有些时候,可能需要替换或增强由这个新类的某个超类所定义的现有方法。

Objective-C提供某种方法来重新方法,并且仍然调用超类的实现方式。为了调用继承方法的实现,需要使用super作为方法调用的目标。

继续沿用前面给出的例子,假设我们发现之前采用的坐标有偏差,实际上的X坐标应为原有的X-10。我们便可在子类MyPoint中对Point类的Show()方法进行如下重写。

@implementation MyPoint   



- (void) Show{  XX = X - 10;  [super Show];  



}    


// Show @end  // MyPoint 

从上面的代码中,我们通过向super发送Show消息使用了超类的相应代码。

相关推荐