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

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

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

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

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

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

 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子类:blog

 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() 主函数则彻底不用修改,就能够运行,运行结果和以前的同样:ci

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

  在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变量中。

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

相关文章
相关标签/搜索