《objective-c基础教程》学习笔记(五)—— 继承方法

  在上一篇博文中,我们将原先的纯C语言代码,编写成了用Objective-C(后面直接缩写成OC)的写法。使得代码在易读性上有明显提升,结构也更清晰。同时,也对面向对象的概念有了进一步的介绍和加深。

  但是,通过上一个例子,我们发现代码的冗余还是很大。像Circle,Rectangle和Egg的定义和实现方法几乎代码都是基本相同,只有个别地方不同。那么,有什么好方法来优化这些代码呢?今天这篇博文的重点就是要介绍继承这个方法,它将会有效的解决上面说的这个问题。

  正如你从亲生父母那里继承一些特性(头发的颜色,鼻子的形状等)一样,面向对象中的继承表明一个类从另外一个类——它的父类或超类(另一种叫法)中获取了某些特性。也就是说,Circle,Rectangle和Egg是从Shape类继承而来的,因此它们将获得Shape类的属性。

  那么,首先先给大家介绍下,在OC中,继承的语法格式。其实,在之前几篇博文中已经看到。声明一个类的时候,@interface Circle :NSObject。这里的冒号,就是继承的标示符,冒号后面的NSObject就是要继承的类,也就是说是父类(使用Cocoa框架的时候,要继承)。注:在OC中,不支持多继承

  好了,介绍了基本的继承的知识。接下来,我们就开始动手修改代码吧。我们的思路是:先定义一个总的Shape父类,定义好方法和属性,然后继承父类。

 1 #import <Foundation/Foundation.h>

 2 /* 1. enum 枚举类型 */

 3 //定义绘制图形的类型: 圆形,矩形,椭圆形

 4 typedef enum{

 5     kCircle,

 6     kRectangle,

 7     kEgg

 8 } ShapeType;

 9 

10 //定义绘制图形的颜色: 红色,绿色和蓝色

11 typedef enum{

12     kRedColor,

13     kGreenColor,

14     kBlueColor

15 } ShapeColor;

16 

17 /* 2. struct 结构体 */

18 //定义图形的基本属性

19 typedef struct{

20     int x, y, width, height;

21 } ShapeRect;

22 

23 NSString *colorName (ShapeColor fillColor)

24 {

25     switch(fillColor)

26     {

27         case kRedColor:

28             return @"red";

29             break;

30         case kGreenColor:

31             return @"green";

32             break;

33         case kBlueColor:

34             return @"blue";

35             break;

36     }

37 }

38 

39 /* 3. 定义Shape父类*/

40 @interface Shape: NSObject{

41     ShapeColor fillColor;

42     ShapeRect bounds;

43 }

44 -(void) setFillColor:(ShapeColor) fillColor;

45 -(void) setBounds:(ShapeRect) bounds;

46 -(void) draw;

47 @end //Shape

48 

49 /* 实现Shape父类 */

50 @implementation Shape

51 -(void) setFillColor:(ShapeColor) c

52 {

53     fillColor = c;

54 }

55 -(void) setBounds:(ShapeRect) b

56 {

57     bounds = b;

58 }

59 -(void) draw{

60 }

61 @end

  虽然draw方法什么功能也没实现,但是还是需要定义。以便Shape的所有子类可以通过它去实现各自的方法。

  然后,我们分别定义Circle,Rectangle和Egg子类:

 1 /*定义Circle,继承Shape父类*/

 2 @interface Circle: Shape

 3 @end

 4 

 5 /*定义Rectangle,继承Shape父类*/

 6 @interface Rectangle: Shape

 7 @end

 8 

 9 /*定义Egg,继承Shape父类*/

10 @interface Egg: Shape

11 @end

  接下来,对子类的draw方法进行实现,代码如下:

 1 @implementation Circle

 2 -(void) draw

 3 {

 4     NSLog(@"drawing a circle at (%d %d %d %d) in %@",

 5           bounds.x,

 6           bounds.y,

 7           bounds.height,

 8           bounds.width,

 9           colorName(fillColor));

10 }

11 @end

12 

13 @implementation Rectangle

14 -(void) draw

15 {

16     NSLog(@"drawing a rectangle at (%d %d %d %d) in %@",

17           bounds.x,

18           bounds.y,

19           bounds.height,

20           bounds.width,

21           colorName(fillColor));

22 }

23 @end

24 

25 @implementation Egg

26 -(void) draw

27 {

28     NSLog(@"drawing an egg at (%d %d %d %d) in %@",

29           bounds.x,

30           bounds.y,

31           bounds.height,

32           bounds.width,

33           colorName(fillColor));

34 }

35 @end

  通过用继承方法的修改,代码冗余问题明显感觉好了很多。Main() 主函数则完全不用修改,就可以运行,运行结果和之前的一样:

《objective-c基础教程》学习笔记(五)—— 继承方法

  在上面的例子中,我们在子类中重新实现了draw的方法,这个过程叫重写方法。执行的时候,如果子类中有重新定义父类中的方法,那么就会先去执行子类方法,父类中的同名方法则会别忽略。如果子类方法找不到,再去执行父类中定义的方法。

  在OC中,也提供了既可以重写方法实现,又可以调用父类自身实现的方法。为了调用继承的方法在父类中出现,需要使用super作为方法调用的目标。当我们向super发送信息的时候,实际上是请求OC向该类的父类发送消息。下面就修改一个使用super关键字的例子:

 1 @implementation Circle

 2 -(void) setFillColor:(ShapeColor) c

 3 {

 4     if(c == kRedColor)

 5     {

 6         c = kGreenColor;

 7     }

 8     [super setFillColor: c];

 9 }

10 -(void) draw

11 {

12     NSLog(@"drawing a circle at (%d %d %d %d) in %@",

13           bounds.x,

14           bounds.y,

15           bounds.height,

16           bounds.width,

17           colorName(fillColor));

18 }

19 @end

  我修改了下Circle类的实现方法,对setFillColor方法进行了重新。假如调用的颜色是红色,则返回的是绿色。在函数的结尾处,使用super关键字,通知父类,将新的颜色存储在fillColor变量中。

  好了,今天对继承的介绍就先在这告一段落吧。晚安,各位!

你可能感兴趣的:(Objective-C)