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


  本文标签:Objective-C 面向对象 继承

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

  1. Point : NSObject  
  2. {  
  3.   int X;  
  4.   int Y;  
  5. }  
  6. - (void) SetX: (int) X;  
  7. - (void) SetY: (int) Y;  
  8. - (void) Show;  
  9. // 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

  1. - (void) SetX: (int) thisX  
  2. {  
  3.   X = thisX;  
  4. } // SetX  
  5.  
  6. - (void) SetY: (int) thisY  
  7. {  
  8.   X = thisY;  
  9. } // SetY  
  10.  
  11. - (void) Show  
  12. {  
  13.   NSLog(Point at (%d, %d)", X, Y);  
  14. } // Show  
  15. // Point 

  下面进行逐句分析  。

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

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

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

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

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

  实例化对象

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

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

  1. [Point new] 

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

  1. int main (int argc, const char* argv[]){  id thisPoint;  
  2.    thisPoint = [Point new];   
  3.     [thisPoint SetX: 0];   
  4.      [thisPoint SetY: 0];     
  5.      [thisPoint Show];  
  6.  }    
  7. // 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部分声明新类的时候,其实已经用到了继承的语法  。

  1. @interface Point : NSObject  

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

  1. @interface MyPoint : Point@end  // MyPoint 

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

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

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

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

  1. @implementation MyPoint   
  2. - (void) Show{  XX = X - 10;  [super Show];  
  3. }    
  4. // Show @end  // MyPoint 

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

  这里的super既不是参数也不是实例变量,向super发送消息时,实际上是在请求Objective-C向该类的超类发送消息  。如果超类中没有定义该消息,Objective-C将按照惯常的方式在继承链中继续查找对应的消息  。

  小结:详解Objective-C学习笔记之面向对象编程的内容介绍完了,希望本文对你有所帮助  。