OC教程2继承与复合

OC2

本章教程主要讨论OC的继承语法以及类的复合编程模式。

  1. OC继承语法
  2. OC语言的动态特性
  3. OC的复合模式
  4. 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

在这里我们先补充一下属性括号中的内容。

属性括号中的内容为属性控制符,分别对属性的读写权限,内存管理和线程操作做出相关规定。

  1. 读写权限由两个关键字控制,分别为:readonlyreadwrite。其中如果不写默认为readwrite。通常属性的读写权限都为可读可写。
  2. 内存管理权限由四个关键字控制,分别为:assgin,strong,weakcopy。如果不写,默认为assgin。如果属性类型为基本数据类型,那么只能用assgin。如果属性类型为对象指针,一般情况下用strong,特殊情况下用weakcopy。特殊情况在后面的内存管理章节会展开讲解。
  3. 线程操作权限由两个关键字控制,分别为:atomicnonatomic。其中如果不写默认为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关键字

通常继承和复合会一同使用,来快速构造一个复杂的对象。

例如现在有一个需求,要求我们快速制作一个可以除甲醛的高级空调。通常我们并不是从零开始研发,而是基于一定基础开始制作。

在这里,我提供了两个对象作为研发的基础

  1. Kongtiao类,具有制冷方法
  2. 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

这样我们在使用高级空调制冷的同时,也同时能够除甲醛了。

时间: 2024-10-11 11:32:47

OC教程2继承与复合的相关文章

【《Objective-C基础教程 》笔记ch04】(五)OC中的继承inheritance机制

一.为什么需要继承 使用继承一方面继承了父类的特性,另一方便解决了重复代码维护问题. 二.继承之语法 1. @interface 子类名:父类名 2. OC只支持单继承,不支持继承多个父类. 3. 重构--移植和优化代码. 三. 继承的工作机制 1. 方法调度 子类拥有一个指向它父类的引用指针,消息传递时,OC的方法调度机制使用该信息来找到正确的实现方法,查找过程是现在子类中找,找不到再到父类中继续找. 2. 实例变量 1)继承实例源码 @interface Shape : NSObject {

面向对象的三大基石(封装,继承和复合,多态)

转自 面向对象的三大基石面向对象的三大基石(封装,继承和复合,多态) 三大基石之一 封装 1.什么是封装? 封装(encapsulation)又叫隐藏实现(Hiding the implementation).就是只公开代码单元的对外接口,而隐藏其具体实现. 比如你的手机,手机的键盘,屏幕,听筒等,就是其对外接口.你只需要知道如何按键就可以使用手机,而不需要了解手机内部的电路是如何工作的.封装机制就像手机一样只将对外接口暴露,而不需要用户去了解其内部实现.细心观察,现实中很多东西都具有这样的特点

(转)面向对象的三大基石(封装,继承和复合,多态)

三大基石之一 封装 1.什么是封装? 封装(encapsulation)又叫隐藏实现(Hiding the implementation).就是只公开代码单元的对外接口,而隐藏其具体实现. 比如你的手机,手机的键盘,屏幕,听筒等,就是其对外接口.你只需要知道如何按键就可以使用手机,而不需要了解手机内部的电路是如何工作的.封装机制就像手机一样只将对外接口暴露,而不需要用户去了解其内部实现.细心观察,现实中很多东西都具有这样的特点. 2.如何实现封装?            在程序设计里,封装往往是

OC基础笔记——继承(广州黑马一期)

OC中的继承机制是单继承的,一个子类只能有一个父类 OC支持多层继承的,A 继承 NSObject,B继承A这就称为多层继承 在继承体系中方法调用的顺序 1.在自己类中找 2.如果没有,去父类中找 3.如果父类中没有,就去父类的父类中 4.如果父类的父类也没有,就还往上找,直到找到基类(NSObject) 5.如果NSObject都没有就报错了 //只有继承NSObject那么这个对象才有创建对象能力//NSObject是大部分类的基类(根类 root class),/* 当 A 类 继承 B类

OC的动态继承编译机制

[问]为什么OC不能sizeof一个对象的大小或一个类的大小?和类结构相近的结构体却能够. [再问]为什么OC不能将对象声明到静态空间,如栈中?和类结构相近的结构体却能够. [答]由于OC的动态继承编译机制. 所谓动态继承机制,就是说在编译时,不能确立类之间的继承关系,自然无法确定类的大小. 仅仅有执行时,才确立类之间的继承关系.不能在编译时确定类的大小.自然不能将类的对象创建在栈里.

java中的继承与oc中的继承的区别

为什么要使用继承? 继承的好处: (1)抽取出了重复的代码,使代码更加灵活 (2)建立了类和类之间的联系 继承的缺点: 耦合性太强 在OC中的继承是: 1.OC中不允许子类和父类拥有相同名称的成员变量名:(java中是可以的) 2.编译器从上往下执行,所以在子类前面至少应该要有父类的声明:如 @interface Worker : Person @end 3.OC中的子类可以拥有和父类相同名称的方法,在子类调用时,优先去自己的内部寻找,如果父类没有定义该方法,则继续在继承链上查找,直到找到为止,

OC类的继承以及类的循环调用

一, 关于OC的实例变量的可见度,即实例变量的访问权限有三种: 1),@public           公有的 被@public修饰的实例变量是公共的,即没有访问权限,在任何文件中都可以访问,(访问方式是通过对象+指向操作符) 2),@protected    受保护的 被@protected修饰的实例变量有一定的访问限,只允许在本类文件及子类文件中访问,其他文件不可访问 3),@private         私有的 被@private 修饰的实例变量,只允在在本类文件中访问,不可以在子类文

黑马程序员------OC面向对象之继承

------Android培训.iOS培训.Java培训,期待与您交流----- 一.继承的基本概念 继承是面向的三大特征之一,指的是在一个类的基础上,定义一个新类:原本的类成为父类(基类),新类称为子类(派生类). 生活中,继承的例子也是数不胜数,比如一个儿子继承了他父亲,那么他就享受他父亲的财产了,当然不是全部,详细解释见下文. 再如,一个电器系列: 一层接着一层,电器为父类,下面的洗衣机.电脑.电视机都是电器的子类,下面的品牌名又是洗衣机.电脑.电视机的子类,当然也是电器的子类. 体现在代

Objective-C基础1:OC中类的继承和组合

1.类的定义和声明 OC中的类声明是以@interface开始@end结束. OC中的类定义以@implementation开始@end结束. OC中的方法声明: - (void) setName : (NSString*) strName;前面的短线-表示这是一个方法,(void)表示返回值, setName表示方法名称,(NSString*) StrName表示参数是NSString*类型,名称是strName,注意:()一定要加 OC中的成员变量定义在类声明的{}中,这一点跟方法声明不一样