Objective-C中的继承和多态
面向对象编程之所以成为主流的编程思想和他的继承和多态是分不开的,只要是面向对象语言都支持继承和多态,当然不同的OOP语言之间都有其特点。OC中和Java类似,不支持多重继承,但OOP语言C++就支持多继承,为什么OC不支持多继承稍后将会提到。
说到继承呢,想到了一本书上是引用《大话西游》里的一句话来描述继承的。“人是人他妈生的,妖是妖他妈生的!”,想必里面的唐三藏也学过OOP编程,也许他们师徒四人去西天取什么算法导论呢,漫谈OOP编程啦,数据结构啦等这类的书去啦。人和妖都属于动物类,但各自有各自的特点,各自有各自的不同,动物就是父类,而人和妖就是子类。继承的目的是为了减少代码的冗余,还是DRY原则(don`t repeat yourself)。
在Objective-C中super是指向直接父类的指针,而self是指向本身的指针,self就相当于java中的this指针。在OC中写类时可以在@implementation中定义哪些在@interface中无相应声明的方法,但这个方法是私有的,仅在类的实现中使用。
在Objectiv-C中几乎所有的类都是继承自NSObject类,NSObject类中存在大量功能强大的方法。下面对NSObject类中的各种方法进行试验和介绍:
1. +(void) load; 类加载到运行环境时调用该方法
测试:在子类中重写load方法来进行测试, 当重写完load方法,在mian方法中不需要任何实例化任何对象
当类被加载时load就会别调用.load是类方法,可以直接被类调用
|
1
2
3
4
5
|
//重写NSObject中的load方法+(void) load{ NSLog(@"ObjectTest中的load方法被调用啦!!");} |
运行结果:
|
1
|
2014-07-30 08:58:31.704 HelloOC[550:303] ObjectTest中的load方法被调用啦!! |
2. +(void) initialize; 在类第一次使用该类时调用该方法,第二次就不调用了
测试:重写initalize方法
|
1
2
3
4
5
|
//重写initialize方法,会在类第一次使用时调用+(void) initialize{ NSLog(@"initialize方法被调用了(类第一次被实例化)!");} |
运行结果:
|
1
2
|
2014-07-30 09:27:53.767 HelloOC[624:303] load方法被调用啦!!2014-07-30 09:27:53.769 HelloOC[624:303] initialize方法被调用了(类第一次被实例化)! |
3. +(id) alloc: 返回一个已经分配好的内存对象; -(id) init: 对已经分配了内存的实例进行初始化; new同时调用了alloc 和 init
demo: Object *object = [[Object alloc] init];
可以在子类中把alloc进行重写,然后观察运行情况
|
1
2
3
4
5
6
|
//重写alloc方法+(id) alloc{ NSLog(@"alloc函数被调用啦"); return [super alloc];} |
|
1
2
3
4
5
6
7
|
//重写init-(id) init{ NSLog(@"init被调用了"); self = [super init]; return self;} |
测试方法一个用alloc和init实例化类,一个用new实例化类:
|
1
2
3
4
5
|
//第一次使用ObjectTest类ObjectTest *o1 = [[ObjectTest alloc] init];//第一次使用ObjectTest类ObjectTest *o2 = [ObjectTest new]; |
运行结果:
|
1
2
3
4
5
6
|
2014-07-30 09:59:58.991 HelloOC[689:303] load方法被调用啦!!2014-07-30 09:59:58.993 HelloOC[689:303] initialize方法被调用了(类第一次被实例化)!2014-07-30 09:59:58.993 HelloOC[689:303] alloc函数被调用啦2014-07-30 09:59:58.993 HelloOC[689:303] init被调用了2014-07-30 09:59:58.994 HelloOC[689:303] alloc函数被调用啦2014-07-30 09:59:58.994 HelloOC[689:303] init被调用了 |
4.-(void)dealloc 释放对象自身所占有的内存;
5. -(Class)class 或者 +(Class)class 返回当前对象的所属类; -(Class)superclass 或者 +(Class)superclass返回当前类的父类
|
1
2
3
4
5
6
7
|
//返回当前对象所对应的类NSString *className =(NSString *) [self class];NSLog(@"%@类的display方法", className);//返回当前对象所对应的父类NSString *superClassName = (NSString *) [self superclass];NSLog(@"%@类的父类是%@", className, superClassName); |
6、-(BOOL)isKindOfClass : (Class)aClass 判断某个实例是否属于某个类或者子类的对象
事例代码如下:
|
1
2
3
4
5
|
//isKindOfClass的用法BOOL b = [o2 isKindOfClass:[ObjectTest class]];if (b == YES) { NSLog(@"o2是ObjectTest类的对象");} |
7.-(BOOL)isMemberOfClass:(Class)aClass; 只能判断摸个实例是否属于某个类,不能判断是否属于某个父类;
|
1
2
3
4
5
|
//isMemberOfClassBOOL result = [o2 isMemberOfClass:[NSObject class]];if (result == NO) { NSLog(@"isMemberOfClass不能判断是否为NSObject子类的对象");} |
8.-(NSString *) description; 返回字符串形式对象的描述,方便调试
|
1
2
3
|
//descriptionNSString *descript = [o2 description];NSLog(@"%@", descript); |
输出结果: <ObjectTest: 0x100206650>
9.-(NSUInteger) hash; 返回对象的哈希值;
|
1
2
3
|
//hash的用法NSUInteger hash = [o2 hash];NSLog(@"%p", hash); |
输出结果:2014-07-30 11:40:35.685 HelloOC[1130:303] 0x100107b70
10.-(BOOL) isEqual:(id)object; 比较两个对象是否相同,默认是使用地址进行比较的,且hash值一定要相同
|
1
2
3
4
5
6
7
8
9
10
11
|
//isEqual的用法NSString *str1 = @"111";NSString *str2 = str1;if ([str2 isEqual:str1] == YES){ NSLog(@"str2 == str1");}else{ NSLog(@"str2 != str1");} |
Objective-C中的继承
继承是is-a的关系,比如猫咪是一个动物,那么动物是父类,而猫咪是动物的子类。子类具有父类的属性和 行为,以及自身的属性和行为,也就是说“父类更一般,子类更具体”。用一个富二代的类来说明一下类的继承。
1.先定义一个富人的类
代码说明:
1.声明访问权限为@protected的三个属性,分别为三个属性用@property加上getter和setter方法
2.并为该类创建便利初始化方法和便利构造器
3.为富人类定义一个刷卡方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
//// Richer.h// HelloOC//// Created by ludashi on 14-7-29.// Copyright (c) 2014年 ludashi. All rights reserved.//#import <Foundation/Foundation.h>@interface Richer : NSObject{ @protected NSString *name; int age; NSString *gender;}//定义富人的姓名,年龄,性别,并为其提供getter和setter方法@property (copy, nonatomic) NSString *name;@property (assign, nonatomic) int age;@property (copy, nonatomic) NSString *gender;//定义便利初始化方法-(id) initWithName : (NSString *)vName AndAge : (int)vAge AndGender : (NSString *)vGender;//定义便利构造器+(id) richerWithName : (NSString *)vName AndAge : (int)vAge AndGender : (NSString *)vGender;//定义刷卡方法-(void) poss;@end |
2.为富人类编写实现代码
代码说明:
1.用@synthesize实现getter和setter方法
2.实现便利初始化方法,用[ super init ]初始化富人类的直接父类,也就是NSObject
3.使用便利构造器返回实例化并初始化后的对象
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#import "Richer.h"@implementation Richer//实现getter和setter方法@synthesize name, age, gender;//实现便利初始化函数-(id) initWithName : (NSString *)vName AndAge : (int)vAge AndGender : (NSString *)vGender{ if (self = [super init]) { self->name = vName; self->age = vAge; self->gender = vGender; } return self;}//实现便利构造器+(id) richerWithName:(NSString *)vName AndAge:(int)vAge AndGender:(NSString *)vGender{ Richer *richer = [[Richer alloc] initWithName:vName AndAge:vAge AndGender:vGender]; return richer;}//实现刷卡方法-(void) poss{ NSLog(@"%@有钱你就刷吧", name);}@end |
3.编写富二代的类,富二代和富人有许多相似的属性和方法所以富二代继承于富人类,并添加相应的属性和方法,把需要重写的方法进行重写。
代码说明:
1.为富二代类添加新的爱好属性
2.为富二代添加新的方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#import "Richer.h"@interface Richer2nd : Richer//Richer2nd继承啦Richer所有的方法//为富二代添加新的属性@property (copy, nonatomic) NSString *hobby;//便利初始化函数-(id) initWithName : (NSString *) vName AndAge : (int)vAge AndGender : (NSString *) vGender AndHobby : (NSString *)vHobby;//为Richer2nd编写便利构造器+(id)richer2ndWithName : (NSString *) vName AndAge : (int)vAge AndGender : (NSString *) vGender AndHobby : (NSString *)vHobby;//添加hobby方法-(void) myHobby;@end |
4.各种方法的实现
代码说明:
1.在编写便利初始化方法时利用super来调用父类的便利初始化方法来把继承到的父类的方法进行初始化
2.用self给新添加的属性进行初始化
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#import "Richer2nd.h"@implementation Richer2nd//实现属性的getter和setter方法@synthesize hobby;//编写便利初始化函数,复用父类的便利初始化方法-(id)initWithName:(NSString *)vName AndAge:(int)vAge AndGender:(NSString *)vGender AndHobby:(NSString *)vHobby{ if (self = [super initWithName:vName AndAge:vAge AndGender:vGender]) { self->hobby = vHobby; } return self;}//编写便利构造函数+(id)richer2ndWithName:(NSString *)vName AndAge:(int)vAge AndGender:(NSString *)vGender AndHobby:(NSString *)vHobby{ Richer2nd *richer = [[Richer2nd alloc] initWithName:vName AndAge:vAge AndGender:vGender AndHobby:vHobby]; return richer;}//重写刷卡方法-(void)poss{ [super poss]; NSLog(@"我是富二代,我爸有钱,我就刷!");}//添加新的方法-(void) myHobby{ NSLog(@"我是富二代%@,我超喜欢%@", name, hobby);}@end |
5.以下是上面代码的运行结果
|
1
2
3
4
|
2014-07-30 08:38:12.956 HelloOC[483:303] Bill有钱你就刷吧2014-07-30 08:38:12.957 HelloOC[483:303] BILL`s son有钱你就刷吧2014-07-30 08:38:12.958 HelloOC[483:303] 我是富二代,我爸有钱,我就刷!2014-07-30 08:38:12.958 HelloOC[483:303] 我是富二代BILL`s son,我超喜欢飙车 |
Objective-C中的多态
多态简单的说就是对于不同对象响应同一个方法时做出的不同反应。在 OC中动态类型id是实现多态的一种方式,id是一个独特的数据类型,可以转换为任何数据类型,上面的富人和富二代可以这样定义
|
1
2
3
4
5
6
7
8
9
10
|
id richer = nil;//测试富人类richer = [Richer richerWithName:@"Bill" AndAge:40 AndGender:@"Man"];[richer poss];//测试富二代的类richer = [Richer2nd richer2ndWithName:@"BILL`s son" AndAge:16 AndGender:@"男" AndHobby:@"飙车"];[richer poss];[richer myHobby]; |
上面程序的输出结果和继承部分的结果是一致的;
多态的另一个例子: Animal是父类,子类有Cat 和 Dog,子分别重写了父类中的eat方法;实例化对象的时候可以用下面的方法:
|
1
2
3
4
5
6
7
|
Animal *animal = nil; //实例化猫的对象
animal = [Cat new];[animal eat]; //实例化狗的对象
animal = [Dog new];[animal eat]; |
面向对象编程中的OCP原则和LSP原则
OCP : Open Closed Principle原则, 对扩展开放,对修改关闭
LSP :里氏代换原则,任何基类可以出现的地方,子类一定可以出现。
Objective-C中的继承和多态的更多相关文章
- C中的继承和多态
昨天同学面试被问到这个问题,很有水平,以前都没有遇到过这个问题,一时自己也不知道怎么回答. 网上学习了一下,记录以备后用! C/C++ Internals : 里面的问题都写的不错,可以读读! Ref ...
- Python面向对象中的继承、多态和封装
Python面向对象中的继承.多态和封装 一.面向对象的三大特性 封装:把很多数据封装到⼀个对象中,把固定功能的代码封装到⼀个代码块, 函数,对象, 打包成模块. 这都属于封装思想. 继承:⼦类可以⾃ ...
- java中的继承 和多态。
package com.aaa.zxf.ajax.test; /** *一. java 中的继承和多态. * * 继承的特性? * 1.实现继承的方式 * A 如何建立继承关系(一个类继承于 另一个类 ...
- Python 中的继承、多态和封装
涉及问题: Python 中如何实现多继承,会有什么问题? Python 中的多态与静态方法有什么区别? 答案要点如下: Python 中的继承,就是在定义类时,在括号中声明父类,简单示例如下: cl ...
- 2017.10.10 java中的继承与多态(重载与重写的区别)
1. 类的继承 继承是面向对象编程技术的主要特征之一,也是实现软件复用的重要手段,使用继承特性子类(subclass) 可以继承父类(superclass)中private方法和属性,继承的目的是使程 ...
- Java中的继承和多态
1. 什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更 ...
- 简谈java 中的 继承和多态
继承(extends) : 1:object 是所有类的父(基)类. 2:子类继承父类所有的内容除了(private修饰的和构造方法). 3:子类在手动创建构造方法时,必须调用父类构造方法. 4:在J ...
- 【Java学习笔记之十六】浅谈Java中的继承与多态
1. 什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更 ...
- python中的继承和多态
继承 继承的表现方式: class Animal(): pass class Cat(Animal): #animal是cat的父类,也可以说是基类 pass print(Cat.__bases__) ...
随机推荐
- Task异步编程
Task异步编程中,可以实现在等待耗时任务的同时,执行不依赖于该耗时任务结果的其他同步任务,提高效率. 1.Task异步编程方法签名及返回值: a) 签名有async 修饰符 b) 方法名以 Asyn ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- SQL Server CONVERT() 截取日期
SELECT CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AMSELECT CONVERT(varchar(100), GETDATE() ...
- 四、jquery中的事件与应用
当用户浏览页面时,浏览器会对页面代码进行解释或编译--这个过程实质上是通过时间来驱动的,即页面在加载时,执行一个Load事件,在这个事件中实现浏览器编译页面代码的过程.时间无论在页面元素本身还是在元素 ...
- Unity3D 与android交互流程步骤
1.Android端代码可以在Eclipse中开发(AndroidStudio没有试,应该也可以) 2.Unity3D端代码要在Unity中开发 3.Android和Unity3D端,两边都需要加入一 ...
- SDOI 2016 排列计数
题目大意:一个数列A,n个元素,其中m个元素不动,其他元素均不在相应位置,问有多少种排列 保证m个元素不动,组合数学直接计算,剩余元素错位排列一下即可 #include<bits/stdc++. ...
- LA
grmon -altjtag -u 公式rand()%(b-a),是求范围随机数的计算公式,%是做求余运算,正整数对n求余的范围肯定是在0~n-1之间,也就是rand()%(b-a)的范围是0~b-a ...
- 浅谈WEB安全性(前端向)
相信进来的时候你已经看到alert弹窗,显示的是你cookie信息(为配合博客园要求已删除).单纯地在你的客户端弹出信息只是类似于迫使你在自己的房间脱衣服——没人看得到,自然也不算啥恶意行为.那么如果 ...
- 使用VS+VisualGDB编译Linux版本RCF
RPC通信框架--RCF介绍中说了,RCF本身是支持跨平台的,其代码放到Linux平台,是可以通过gcc.make等工具,编译通过的. 官方提供的源码中,只有cmake编译脚本,并没有提供Makefi ...
- 搭建前端私有npm杂记
随着前端队伍越来越壮大,项目间共享代码就变得尤为重要.常用的框架/类库没必要在每个项目都放一份,团队内部产出的公共模块也需要有合理的共享机制.现在,用npm管理前端代码已经是业界趋势.楼主尝试用私有n ...