在上一篇博文中,我们将原先的纯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. Java基础-多线程-②多线程安全问题

    什么是线程的安全问题? 上一篇 Java基础-多线程-①线程的创建和启动 我们说使用实现Runnable接口的方式来创建线程,可以实现多个线程共享资源: class Dog implements Ru ...

  2. C# Dictionary<TKey,TValue>如何添加键重复的内容

    这里以Dictionary<string,string>为例 当我们实例化Dictionary<string,string>集合时,其中有一个重载构造方法如下: // // 摘 ...

  3. [原创]推荐一些在线API生成工具

    [原创]推荐一些在线API生成工具 最近发现Api文档维护是个大体力活,版本控制文档统一化特别麻烦,寻思着这个怎么处理,经高人指点开源有一些工具不错,具体如下: 1.Swagger   http:// ...

  4. Adding Digital control to Dual tracking LM317 / LM337 Bench supply

    Adding Digital control to Dual tracking LM317 / LM337 Bench supply I've been working on my own idea ...

  5. p4中如何rollback/backout merge/integration

    原文: http://answers.perforce.com/articles/KB_Article/How-To-Rollback-An-Integration 当我们需要将一个branch上的代 ...

  6. [Axure RP] – 鼠标滑入按钮时自动下拉表单的设计示例

    转:http://blog.qdac.cc/?p=2197 Axure RP 是个好东东呀,大大方便了程序员与客户之间的前期调研时的交流.不过有一些控制并没有鼠标移入和移出的操作,比如 HTML 按钮 ...

  7. centos7 设置tomcat自启动

    1 .vi  /etc/init.d/tomcat8 #!/bin/bash # # tomcat startup script for the Tomcat server # # chkconfig ...

  8. Convolutional Neural Networks: Application

    Andrew Ng deeplearning courese-4:Convolutional Neural Network Convolutional Neural Networks: Step by ...

  9. SpringBoot使用Mybatis注解开发教程-分页-动态sql

    代码示例可以参考个人GitHub项目kingboy-springboot-data 一.环境配置 1.引入mybatis依赖 compile( //SpringMVC 'org.springframe ...

  10. 解决 Docker pull 出现的net/http: TLS handshake timeout 的一个办法

    echo "DOCKER_OPTS=\"\$DOCKER_OPTS --registry-mirror=http://f2d6cb40.m.daocloud.io\"&q ...