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

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

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

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

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

 #import <Foundation/Foundation.h>
/* 1. enum 枚举类型 */
//定义绘制图形的类型: 圆形,矩形,椭圆形
typedef enum{
kCircle,
kRectangle,
kEgg
} ShapeType; //定义绘制图形的颜色: 红色,绿色和蓝色
typedef enum{
kRedColor,
kGreenColor,
kBlueColor
} ShapeColor; /* 2. struct 结构体 */
//定义图形的基本属性
typedef struct{
int x, y, width, height;
} ShapeRect; NSString *colorName (ShapeColor fillColor)
{
switch(fillColor)
{
case kRedColor:
return @"red";
break;
case kGreenColor:
return @"green";
break;
case kBlueColor:
return @"blue";
break;
}
} /* 3. 定义Shape父类*/
@interface Shape: NSObject{
ShapeColor fillColor;
ShapeRect bounds;
}
-(void) setFillColor:(ShapeColor) fillColor;
-(void) setBounds:(ShapeRect) bounds;
-(void) draw;
@end //Shape /* 实现Shape父类 */
@implementation Shape
-(void) setFillColor:(ShapeColor) c
{
fillColor = c;
}
-(void) setBounds:(ShapeRect) b
{
bounds = b;
}
-(void) draw{
}
@end

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

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

 /*定义Circle,继承Shape父类*/
@interface Circle: Shape
@end /*定义Rectangle,继承Shape父类*/
@interface Rectangle: Shape
@end /*定义Egg,继承Shape父类*/
@interface Egg: Shape
@end

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

 @implementation Circle
-(void) draw
{
NSLog(@"drawing a circle at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.height,
bounds.width,
colorName(fillColor));
}
@end @implementation Rectangle
-(void) draw
{
NSLog(@"drawing a rectangle at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.height,
bounds.width,
colorName(fillColor));
}
@end @implementation Egg
-(void) draw
{
NSLog(@"drawing an egg at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.height,
bounds.width,
colorName(fillColor));
}
@end

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

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

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

 @implementation Circle
-(void) setFillColor:(ShapeColor) c
{
if(c == kRedColor)
{
c = kGreenColor;
}
[super setFillColor: c];
}
-(void) draw
{
NSLog(@"drawing a circle at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.height,
bounds.width,
colorName(fillColor));
}
@end

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

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

《objective-c基础教程》学习笔记(五)—— 继承方法的更多相关文章

  1. Python基础教程学习笔记:第一章 基础知识

    Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...

  2. 【学习笔记】Python基础教程学习笔记

    教程视频网盘共享:http://pan.baidu.com/s/1hrTrR5E 03-python基础.if判断 print 输出数据 print("hahahah")----- ...

  3. 匿名内部类--毕向东java基础教程学习笔记

    1.匿名内部类其实就是内部类的简写形式. 2.定义匿名内部类的前提: 该内部类必须继承一个类,或者实现一个接口. 3.匿名内部类的格式:new 父类名或接口名(){定义子类内容:} 4.其实匿名内部类 ...

  4. 异常处理——毕向东Java基础教程学习笔记

    1.异常:就是程序运行过程中出现的不正常情况. 异常的由来:问题本身也是日常生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象.                        其实 ...

  5. 《嵌入式Linux基础教程学习笔记一》

    常用书目下载地址:http://www.cnblogs.com/pengdonglin137/p/3688029.html 第二章 1.进程上下文和中断上下文(Page20) 当应用程序执行系统调用, ...

  6. 内部类--毕向东Java基础教程学习笔记

    内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...

  7. Objective-C基础教程学习笔记(附录)从Java转向Objective-C

    Java接口与Objective- C正式协议类似,因为它们都需要实现一组方法.Java具有抽象类,但Objective-C没有.Java具有类变量,但在Objective-C中, 可以使用文件范围内 ...

  8. Python基础教程学习笔记:第二章 列表和元组

    1.序列中元素的索引: 第一个元素索引是0,第二个是1,依次递增 最后一个元素索引是-1,倒数第二个是-2,依次递减 2.序列(Sequence)的种类: 列表(list).元组(tuple).字符串 ...

  9. PHP学习笔记五【方法】

    <?php $num1=34; $num2=90; $oper="+"; $res=0; switch($oper) { case "+": $res=$ ...

  10. C++基础 学习笔记五:重载之运算符重载

    C++基础 学习笔记五:重载之运算符重载 什么是运算符重载 用同一个运算符完成不同的功能即同一个运算符可以有不同的功能的方法叫做运算符重载.运算符重载是静态多态性的体现. 运算符重载的规则 重载公式 ...

随机推荐

  1. oracle 列相减——(Oracle分析函数Lead(),Lag())

    lag和lead函数,用于取出数据的前n行的数据和后n行的数据,当然要和over(order by)一起组合 其实这2个函数的作用非常好理解,Lead()就是取当前顺序的下一条记录,相对Lag()就是 ...

  2. protobuf 测试使用

    1       介绍 Protocol buffers are a flexible, efficient, automated mechanism for serializing structure ...

  3. C#用WebBrowser与WIN API辅助模拟获取网站完整Cookie

    网上找到的可以完整获取Cookie的方法,转载一下希望能帮助更多人. 亲测可用 在Winform中使用WebBrowser控件获取网站的Cookie有时候是不完整的,默认调用Document.Cook ...

  4. [Android Pro] AndroidX重构和映射

    原文地址:https://developer.android.com/topic/libraries/support-library/refactor https://blog.csdn.net/ch ...

  5. 微信小程序富文本渲染组件html2wxml及html2wxml代码块格式化在ios下字体过大问题

    1.组件使用: 之前微信小程序的富文本渲染组件用的wxParse,对普通富文本确实可以,但是对于代码格式pre标签则无法使用. 下面这个html2wxml很不错,可以支持代码高亮. 详细文档:http ...

  6. python 获取前一天或前N天的日期

    简单实现 import datetime # 获取前1天或N天的日期,beforeOfDay=1:前1天:beforeOfDay=N:前N天 def getdate(self,beforeOfDay) ...

  7. Postgres空间地理类型POINT POLYGON实现附近的定位和电子围栏功能

    目录 需求和背景 安装插件postgis 点POINT类型和距离 表添加POINT类型 添加空间索引 插入点 两个点之间的距离 附近5公里内的点 最近的10个点 面多边形'POLYGON' 添加字段类 ...

  8. MongoDB 进程控制系列一:查看当前正在执行的进程

    1:查看MongoDB当前正在做哪些操作? db.currentOp() 等同于: db.$cmd.sys.inprog.findOne() 2:查看当前有多少个连接? db.serverStatus ...

  9. [转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码

    本文转自:http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html 〇.目录 一.前言 二.工具准备 三.T4代码生成预热 (一) 单文件生成:Hello ...

  10. texlive测试是否安装成功

    在完成TEX Live安装之后,自然你会希望试试看它是否正常工作,好让你在以后能够创建优美的文档和字体. 1.首先确认你可以执行tex程序: >tex --version TeX 3.14159 ...