OC教程2继承与复合
OC2
本章教程主要讨论OC的继承语法以及类的复合编程模式。
- OC继承语法
- OC语言的动态特性
- OC的复合模式
- super关键字
1,OC继承语法
OC语法只支持单根继承,即一个类只能有一个父类。
继承关键字为
:
@interface 类目 : 父类名
例如我们昨天声明的三角形类
@interface Triangle : NSObject @end
表示Triangle类是继承与NSObject类。Triangle是NSObject的子类,NSObject是Triangle的父类。
OC语法中规定,通过继承方式,可以继承父类的所有方法和除私有权限以外的所有成员变量。
例如上一章的三角形类
@interface Triangle : NSObject @property double a; @property double b; @property double c; -(instancetype)initWithA:(double)a B:(double)b C:(double)c; -(double)area; @end
@implementation Triangle - (instancetype)initWithA:(double)a B:(double)b C:(double)c { self = [super init]; if (self) { self.a = a; self.b = b; self.c = c; } return self; } -(double)area { double s=(_a+_b+_c)/2; return sqrt(s*(s-_a)*(s-_b)*(s-_c)); }
本章我们可以通过继承的方法创建一个新的三角形类
@interface TriangleSub : Triangle @end
@implementation TriangleSub @end
可以看到我们新创建的TriangleSub类中没有声明任何方法也没有实现任何方法。但是通过继承语法,我们无偿获得了父类的所有方法和成员变量。
TriangleSub * subT = [[TriangleSub alloc] initWithA:10 B:11 C:12]; double s = [subT area]; NSLog(@"s = %g",s);//NSLog函数是OC中向控制台输出信息的函数
2,OC语言的动态特性
OC语言是动态类型语言,其表现为调用方法时,不会依据对象指针类型调用对象方法,而根据对象指针使用的内存类型调用响应的方法。
下面通过代码描述这个特性。
首先我们创建一个测试类TestClass
@interface TestClass : NSObject -(void)test; @end
@implementation TestClass -(void)test { NSLog(@"这里是TestClass类的test方法"); } @end
我们继续创建两个类:
SubA继承与TestClass
@interface SubA : TestClass @end
@implementation SubA //重写父类的方法 -(void)test { NSLog(@"这里是SubA类的test方法"); } @end
SubB继承与TestClass
@interface SubB : TestClass @end
@implementation SubB //重写父类的方法 -(void)test { NSLog(@"这里是SubB类的test方法"); } @end
现在做如下测试
SubA * a = [[SubB alloc] init]; [a test];//这样调用没有编译错误,复合OC的语法规则,那会输出哪个结果。
根据我们之前讲的,OC的动态特性的表现形式
对象指针在调用方法是,不会根据对象指针类型调用响应方法,而是根据对象指针指向的内存类型调用响应的方法
由此可见,对象指针
a
的类型为SubA
类型,但其指向的内存类型为SubB
类型。所以用对象指针调用test方法时,会调用SubB
的test方法。其输出结果为:这里是SubB类的test方法。
由于OC语法动态特性的原因,在编写代码的过程中,对象指针类型只在编译时起作用。在运行过程中没有任何影响。
OC语法推出一个
id
关键字,表示在编译过程中不指定类型。使用
id
类型编写代码对运行不会有任何影响。但在IDE环境中,变无法开启代码自动补全功能,因IDE工具并不知道该对象指针是什么类型,所以无法进行代码自动提示和补全。3,OC的复合模式
在OC的复合模式就是把其他对象作为自身的题部分,以提升自身的功能。
比如我现在要制作一台电脑,电脑需要CPU,显示器,鼠标和键盘等。这些东西的研发都是很复杂的过程。如果现在有成型的CPU等组件,就可以直接用这些组件攒一台电脑。复合模式就是这样。
所有我们在制作电脑前要先找到这些组件。这些组件并不需要我们来制作,有专业的公司提供这些成型的组件。
在本章练习的SDK中提供了如下组件。
KeyBoard 键盘类 BigMouse 鼠标类 Monitor 显示器类 IntelCPU CPU类
下面就用SDK中提供的各种组件来快速制作一台电脑。
首先我们进行电脑类的声明。需要使用的组件都声明成属性,作为电脑类的一部分。
@interface Computer : NSObject @property(strong, nonatomic) KeyBoard * aKeyBoard; @property(strong, nonatomic) BigMouse * aMouse; @property(strong, nonatomic) Monitor * aMonitore; @property(strong, nonatomic) IntelCPU * aCPU; @end
在这里我们先补充一下属性括号中的内容。
属性括号中的内容为属性控制符,分别对属性的读写权限,内存管理和线程操作做出相关规定。
- 读写权限由两个关键字控制,分别为:
readonly
和readwrite
。其中如果不写默认为readwrite
。通常属性的读写权限都为可读可写。 - 内存管理权限由四个关键字控制,分别为:
assgin
,strong
,weak
和copy
。如果不写,默认为assgin
。如果属性类型为基本数据类型,那么只能用assgin
。如果属性类型为对象指针,一般情况下用strong
,特殊情况下用weak
或copy
。特殊情况在后面的内存管理章节会展开讲解。 - 线程操作权限由两个关键字控制,分别为:
atomic
和nonatomic
。其中如果不写默认为atomic
。通常我们使用nonatomic
作为线程操作,其具体内容在后续的多线程章节会展开讲解。然后继续实现电脑类,因CPU等组件是电脑的一部分,所以我们需要重新电脑的初始化方法,在电脑初始化的的同时也初始化各种组件,为其分配内存。
@implementation Computer - (instancetype)init { self = [super init]; if (self) { self.aKeyBoard = [[KeyBoard alloc] init]; self.aMouse = [[BigMouse alloc] init]; self.aMonitore = [[Monitor alloc] init]; self.aCPU = [[IntelCPU alloc] init]; } return self; } @end
经过声明组件属性,为组件的对象指针分配内存。我们就使用成型的组件快速的制作好了一个功能完整的电脑。
4,super关键字
通常继承和复合会一同使用,来快速构造一个复杂的对象。
例如现在有一个需求,要求我们快速制作一个可以除甲醛的高级空调。通常我们并不是从零开始研发,而是基于一定基础开始制作。
在这里,我提供了两个对象作为研发的基础
- Kongtiao类,具有制冷方法
- ChuJiaquan类,具有除甲醛的方法
以下是Kongtiao类的声明
@interface Kongtiao : NSObject -(void)zhiling; @end
以下是ChuJiaquan类的声明
@interface ChuJiaQuan : NSObject -(void)chuJQ; @end
首先明确我们制作的是一个空调,所有我们创建一个高级空调类继承与空调类。
然后高级空调需要有除甲醛的功能,我们通过复合模式,把除甲醛的模块作为高级的空调的一部分。
最后我们重写父类的制冷方法,在制冷过程中添加除甲醛的步骤。但是在重写的方法会覆盖掉父类原有的方法。这里我们需要在重写方法中手动调用父类原始方法。就需要用到
super
关键字。@interface NewKongtiao : Kongtiao @property(strong, nonatomic) ChuJiaQuan * cJQ; @end
@implementation NewKongtiao - (instancetype)init { self = [super init]; if (self) { self.cJQ = [[ChuJiaQuan alloc] init]; } return self; } -(void)zhileng { [super zhileng]; [self.cJQ chuJQ]; } @end
这样我们在使用高级空调制冷的同时,也同时能够除甲醛了。
- 读写权限由两个关键字控制,分别为:
上一篇: Redis 过期键删除策略
下一篇: 关羽一生战功赫赫,他最后真的被灭门了吗?
推荐阅读
-
php环境配置 php5 mysql5 apache2 phpmyadmin安装与配置_PHP教程
-
从ThinkPHP源码讲解_initialize与__construct construct 2 教程 construct 2 破解中文版 failed to initializ
-
spring入门教程之bean的继承与自动装配详解
-
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
-
Sublime Text 2 官方安装版绿化与汉化图文教程
-
Struts2学习教程之拦截器机制与自定义拦截器
-
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
-
《ServerSuperIO Designer IDE使用教程》-2.与硬件网关数据交互,并进行数据级联转发,直到云端。发布:v4.2.1版本
-
Sublime Text 2 官方安装版绿化与汉化图文教程
-
json2.js 入门教程之使用方法与实例分析