《objective-c基础教程》学习笔记(五)—— 继承方法
在上一篇博文中,我们将原先的纯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基础教程》学习笔记(五)—— 继承方法的更多相关文章
- Python基础教程学习笔记:第一章 基础知识
Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...
- 【学习笔记】Python基础教程学习笔记
教程视频网盘共享:http://pan.baidu.com/s/1hrTrR5E 03-python基础.if判断 print 输出数据 print("hahahah")----- ...
- 匿名内部类--毕向东java基础教程学习笔记
1.匿名内部类其实就是内部类的简写形式. 2.定义匿名内部类的前提: 该内部类必须继承一个类,或者实现一个接口. 3.匿名内部类的格式:new 父类名或接口名(){定义子类内容:} 4.其实匿名内部类 ...
- 异常处理——毕向东Java基础教程学习笔记
1.异常:就是程序运行过程中出现的不正常情况. 异常的由来:问题本身也是日常生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象. 其实 ...
- 《嵌入式Linux基础教程学习笔记一》
常用书目下载地址:http://www.cnblogs.com/pengdonglin137/p/3688029.html 第二章 1.进程上下文和中断上下文(Page20) 当应用程序执行系统调用, ...
- 内部类--毕向东Java基础教程学习笔记
内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...
- Objective-C基础教程学习笔记(附录)从Java转向Objective-C
Java接口与Objective- C正式协议类似,因为它们都需要实现一组方法.Java具有抽象类,但Objective-C没有.Java具有类变量,但在Objective-C中, 可以使用文件范围内 ...
- Python基础教程学习笔记:第二章 列表和元组
1.序列中元素的索引: 第一个元素索引是0,第二个是1,依次递增 最后一个元素索引是-1,倒数第二个是-2,依次递减 2.序列(Sequence)的种类: 列表(list).元组(tuple).字符串 ...
- PHP学习笔记五【方法】
<?php $num1=34; $num2=90; $oper="+"; $res=0; switch($oper) { case "+": $res=$ ...
- C++基础 学习笔记五:重载之运算符重载
C++基础 学习笔记五:重载之运算符重载 什么是运算符重载 用同一个运算符完成不同的功能即同一个运算符可以有不同的功能的方法叫做运算符重载.运算符重载是静态多态性的体现. 运算符重载的规则 重载公式 ...
随机推荐
- vscode使用wsl调试代码
第一步在WSL中配好环境 第二步安装CodeRunner即可,在用户配置中加入如下行: "terminal.integrated.shell.windows": "C:\ ...
- [原创]Network Emulator for Windows Toolkit使用介绍
[原创]Network Emulator for Windows Toolkit使用介绍 1 Network Emulator for Windows Toolkit简介 微软在window系统下,可 ...
- What’s Brewing for .NET Developers
Microsoft hosted its premier fall developer event – Connect(); // 2016 in New York on November 16-17 ...
- ERROR: While executing gem … (Gem::RemoteFetcher::FetchError)
原文地址:https://www.zfanw.com/blog/error-while-executing-gem-gem-remote-fetch-error.html 我对命令行下安装 gem 包 ...
- TensorFlow进阶(二)---张量的操作
张量操作 在tensorflow中,有很多操作张量的函数,有生成张量.创建随机张量.张量类型与形状变换和张量的切片与运算 生成张量 固定值张量 tf.zeros(shape, dtype=tf.flo ...
- 【Zookeeper】源码分析之Leader选举(二)之FastLeaderElection
一.前言 前面学习了Leader选举的总体框架,接着来学习Zookeeper中默认的选举策略,FastLeaderElection. 二.FastLeaderElection源码分析 2.1 类的继承 ...
- What is `^M` and how do I get rid of it?
When I open the file in vim, I am seeing strange ^M characters. Unfortunately, the world's favorite ...
- unix缓冲
目的:尽量减少read,write调用的次数. 标准IO提供3种IO: 1.全缓冲.在填满IO缓冲区后才进行实际的IO操作. 2.行缓冲.当输入和输出遇到换行符时,执行IO操作.(设计终端) 3.不带 ...
- 安装SQL Server For Linux(Install SQL Server)
SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图) 1. 安装SQL Server 官网安装指南:https://docs.microsoft.com ...
- 点击LinearLayout使用selector改变TextView字体颜色
[html] view plaincopy <LinearLayout android:clickable="true" android:focusable=" ...