Objective-C语法之继承、封装、多态

来源:互联网 发布:贪心算法设计原则 编辑:程序博客网 时间:2024/05/16 06:03

继承 封装 多态 

1.1继承

编写面向对象的程序时,你所创建的类和对象之间存在一定的关系。他们协同工作才能实现程序相应的功能。创建一个新类时,通常需要定义新类以区别与其他类及现有类。使用继承可以定义一个具有父类所有功能的新类,它继承了父类的这些功能。 继承是面向对象的一个核心概念。在Objective-C的继承体系中,位于最顶层的根类是NSObject我们定义的所有类都是它的子类。子类也叫扩展类或派生类。我们之前使用的分数类Fraction就是NSObject类的派生类。

1.1.1 为什么使用继承

  继承使得子类可以从父类中获得一些属性和已有方法。要注意的是如果子类中要直接使用父类继承过来的实例变量,那么必须将变量声明在接口部分中,而在实现部分声明的变量,子类无法继承使用。在实现部分声明和synthesize的实例变量都是私有的,子类不能直接访问,需要提供设置值和取值方法才可以访问这些变量。

1.1.2继承的语法格式:

  1. #import <Foundation/Foundation.h>  
  2. @interface ClassA:NSObject  
  3.   
  4. @end  
  5.   
  6. @implementation ClassA  
  7.  
  8. @end  
           上面我们新创建了一个类,@interface后面的就是创建的类名,冒号后边就是继承自哪个类,ClassA继承自NSObject,NSObject是Objective-C中的根类。




1.2封装

封装(Encapsulation)主要的用意是依照题意,设计出数据与方法,并将其组合成一所谓的自定义类别类型,其好处是数据已不是次等公民,可以和方法平起平坐,而且数据也受到保护,因为只有类别下定义的方法才可以直接使用。一般的程序语言,如C 程序语言,大都是以函数(function)为主导,数据是次等的,但是如果数据是错误,不管函数编写多么的好,还是会产生所谓的无用输入,无用输出(Garbage In Garbage Out,GIGO)。而且由于每个人的编写风格不同,有人喜欢使用全局变量,有人定义变量时,所使用的名称都是短小的,而且也没有加注释的习惯,造成在维护上需要付出相当多的资源。有鉴于此,面向对象程序设计定义一个规则,将数据(data)和方法(method)都视为一等公民,也就是重要性相同,并利用类别(class),将数据和方法加以封装(encapsulation), 这有如感冒药,里面的药受到胶囊的保护,不易受外界的破坏。此处所说的方法,相当于一般程序语言的函数。有些作者将数据与方法分别以数据成员(data member)和成员函数 (member function)称之。 
Objective-C 将数据和方法封装成类别表示,至于类别要有哪些数据和方法,完全视题目而定。在面向对象的术语中,称类别为萃取式数据类型(Abstract Data Type,ADT),我不想将它译为抽象数据类型,因为本来就很抽象了,越翻越抽象。其实以另一种名称来说可能较为清楚易懂,那就是用户自定义的数据类型(user-defined data type),其根据题意定出它需要哪些数据及其方法,所以可以说类别相当于一般程序语言所谈的数据类型。而对象(object)是什么呢?简单的说就是属于某一类别的变量。若我们已定义水果的类别, 则可说香蕉、梨子、李子、苹果等等皆是属于水果的对象。或是已定义汽车的类别,则保时捷、宝马、法拉利可说是汽车的对象。您可以将对象看成一般程序式程序语言的变量,而类别就是一般程序式程序语言的数据类型。对象
也可以视为类别的实体(instance)。封装主要的功能是将数据隐藏起来,只有此类别所属的方法,亦即实体方法(instance 
method),才能直接存取数据,所以也可以说是在保护数据,不会被外界任意的存取,所以就大大的降低数据的误用,且很容易的知道错误在哪里,从而省下很多的维护成本。面向对象程序设计中的方法可分为两种,一为上述的实体方法,二为类别方法(class method)。主要的差异在于实体方法需要有一对象去引发,而类别方法可以由类别名称触发之。 

一、如何将数据与方法封装起来 
我们以范例来加以说明,从输入两个整数,计算其总和,之后将其输出。为了比较起见,首先以一般的程序设计方式,亦即不是以封装的方式来编写,如范例程序class99 所示: 范例程序class99 
//class99 #import <Foundation/Foundation.h> 
int main (intargc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init]; int num1, num2, total=0; //input num1 = 100; num2 = 200;  } 
//process total = num1 + num2; 
//output NSLog(@"num1=%d, num2=%d", num1, num2); NSLog(@"total=%d", total); [pool drain]; return 0; 输出结果 
num1=100, num2=200 total = 300 
若将上一范例程序以封装的方式来编写的话,则程序将如下所示: 
范例程序class100 //class100 
#import<Foundation/Foundation.h> @interfacemyClass : NSObject { int num1, num2; } 












-(void) setData; -(int) sum; -(void) output; @end 
@implementationmyClass -(void) setData { 
num1=100; num2=200; } 
-(int) sum { 
return (num1+num2); } 
-(void) output { } 
NSLog(@"num1=%d, num2=%d", num1, num2); @end 
int main (intargc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init]; myClass *obj = [[myClassalloc] init]; int total; } 
[objsetData]; total = [obj sum]; [obj output]; NSLog(@"total=%i", total); 
[obj release]; [pool drain]; return 0; 

1.3多态

  一、什么是多态

 

      多态:不同对象以自己的方式响应相同的消息的能力叫做多态。


     由于每个类都属于该类的名字空间,这使得多态称为可能。类定义中的名字和类定义外的名字并不会冲突。类的实例变量和类方法有如下特点:

  • 和C语言中结构体中的数据成员一样,类的实例变量也位于该类独有的名字空间。

  • 类方法也同样位于该类独有的名字空间。与C语言中的方法名不同,类的方法名并不是一个全局符号。一个类中的方法名不会和其他类中同样的方法名冲突。两个完全不同的类可以实现同一个方法。

      方法名是对象接口的一部分。对象收到的消息的名字就是调用的方法的名字。因为不同的对象可以有同名的方法,所以对象必须能理解消息的含义。同样的消息发给不同的对象,导致的操作并不相同。

      多态的主要好处就是简化了编程接口。它容许在类和类之间重用一些习惯性的命名,而不用为每一个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。

      Objective-C支持方法名的多态,但不支持参数和操作符的多态。

 

     二、在Objective-C中如何实现多态

 

     在Objective-C中是通过一个叫做selector的选取器实现的。在Objective-C中,selector有两个意思, 当用在给对象的源码消息时,用来指方法的名字。它也指那个在源码编译后代替方法名的唯一的标识符。 编译后的选择器的类型是SEL有同样名字的方法、也有同样的选择器。你可以使用选择器来调用一个对象的方法。

 

     选取器有以下特点:

     * 所有同名的方法拥有同样的选取器

     * 所有的选取器都是不一样的

 

     (1) SEL和@selector

          选择器的类型是 SEL。@selector指示符用来引用选择器,返回类型是SEL。

          例如:

         SEL responseSEL;      

                responseSEL = @selector(loadDataForTableView:);     

         可以通过字符串来得到选取器,例如:

               responseSEL = NSSelectorFromString(@"loadDataForTableView:");

         也可以通过反向转换,得到方法名,例如:

               NSString  *methodName = NSStringFromSelector(responseSEL);

 

     (2) 方法和选取器

 

         选取器确定的是方法名,而不是方法实现。这是多态性和动态绑定的基础,它使得向不同类对象发送相同的消息成为现实;否则,发送     消息和标准C中调用方法就没有区别,也就不可能支持多态性和动态绑定。

         另外,同一个类的同名类方法和实例方法拥有相同的选取器。

     (3) 方法返回值和@参数类型

 

         消息机制通过选取器找到方法的返回值类型和参数类型,因此,动态绑定(例:向id定义的对象发送消息)需要同名方法的实现拥有相     同返回值类型和相同的参数类型;否则,运行时可能出现找不到对应方法的错误。

         有一个例外,虽然同名灶方法和实例方法拥有相同的选取器,但是它们可以有不同的参数类型和返回值类型。



原创粉丝点击