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
|
//isMemberOfClass BOOL result = [o2 isMemberOfClass:[NSObject class ]]; if (result == NO) { NSLog(@ "isMemberOfClass不能判断是否为NSObject子类的对象" ); } |
8.-(NSString *) description; 返回字符串形式对象的描述,方便调试
1
2
3
|
//description NSString *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__) ...
随机推荐
- 解决overflow:hidden在安卓微信页面没有效果的办法
在做h5移动端时候,发现overflow: hidden;在安卓微信页面失效问题,经研究和实验,用第三种方法和第四种方法可以解决! 1.完全隐藏 在<boby>里加入scroll=&quo ...
- css 清除浮动 clear
.clearfix{ zoom:1;/*对于老版本的IE进行兼容的设置*/ } .clearfix:after{ content:""; display:block; visibi ...
- html websocket
from:http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/ websocket 规范升级过,在该链接的文章内未提及,后面 ...
- Git 常用命令大全
Git常用操作命令: 1) 远程仓库相关命令 检出仓库:$ git clone git://github.com/jquery/jquery.git 查看远程仓库:$ git remote -v 添加 ...
- 如何使用Goolge Timeline工具
网上中文的资料版本比较老,找到一个新版本的英文介绍,翻一下,原文:https://developers.google.com/web/tools/chrome-devtools/profile/eva ...
- ASP.NET Aries 开源开发框架:开发指南(一)
前言: 上周开源了Aries开发框架后,好多朋友都Download了源码,在运行过程里,有一些共性的问题会问到. 所以本篇打算写一下简单的开发指南,照顾一下不是太看的懂源码的同学,同时也会讲解一下框架 ...
- .NET面试题系列[9] - IEnumerable
.NET面试题系列目录 什么是IEnumerable? IEnumerable及IEnumerable的泛型版本IEnumerable<T>是一个接口,它只含有一个方法GetEnumera ...
- Web高级征程:《大型网站技术架构》读书笔记系列
一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...
- ASP.NET MVC 控制器激活(二)
ASP.NET MVC 控制器激活(二) 前言 在之前的篇幅中,用文字和图像来表示了控制器的激活过程,描述的角度都是从框架默认实现的角度去进行描述的,这样也使得大家都可以清楚的知道激活的过程以及其中涉 ...
- 你真的会用java replaceAll函数吗?
replace.replaceAll.replaceFirst这三个函数会java的同学估计都用过,笔者已经用了2年多,可是,我们真的懂他们吗? 概述一下他们三个的用法: · replace(Char ...