多态---父指针指向子类对象(父类引用指向子类对象)
我们都知道,面向对象程序设计中的类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今天就来看一下OC中类的三大特性:
一、封装
封装就是对类中的一些字段,方法进行保护,不被外界所访问到,有一种权限的控制功能,Java中有四种访问权限修饰符:
1
|
public, default ,protected,private
|
访问权限依次递减,这样我们在定义类的时候,哪些字段和方法不想暴露出去,哪些字段和方法可以暴露,可以通过修饰符来完成,这就是封装,下面来看一个例子吧:
Car.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// Car.h
// 05_ObjectDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import
@interface Car : NSObject{
//这个属性就是对外进行保密的相当于private,所以我们需要在外部访问的话,必须定义get/set方法
//默认的是private的,但是我们可以使用@public设置为public属性的,那么在外部可以直接访问:person->capcity = 2.8;
//当然我们一般不这么使用,因为这会破坏封装性,这种用法相当于C中的结构体中权限
//一共四种:@public,@protected,@private,@package,这个和Java中是相同的
@public
float _capcity; //油量属性
}
- (void)run:(float)t;
@end
|
这里我们可以看到,OC中也是有四种访问权限修饰符:
1
|
@public、@protected、@private、@package
|
其中默认的修饰符是@private
但是这里要注意的是:OC中的方法是没有修饰符的概念的,这个和Java有很大的区别,一般都是公开访问的,即public的,但是我们怎么做到让OC中的一个方法不能被外界访问呢?
OC中是这么做的,如果想让一个方法不被外界访问的话,只需要在.m文件中实现这个方法,不要在头文件中进行定义,说白了就是:该方法有实现,没定义,这样外界在导入头文件的时候,是没有这个方法的,但是这个方法我们可以在自己的.m文件中进行使用。
为什么要介绍这点知识呢?因为在后面我们会说到单利模式,到时候就会用到这个知识点了。
二、继承
继承是类中的一个重要的特性,他的出现使得我们没必要别写重复的代码,可重用性很高。当然OC中的继承和Java中是一样的,没多大区别,这里在看一个例子吧:
首先来看一下父类:Car
Car.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//
// Car.h
// 06_ExtendDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import
@interface Car : NSObject{
NSString *_brand;
NSString *_color;
}
- (void)setBrand:(NSString *)brand;
- (void)setColor:(NSString *)color;
- (void)brake;
- (void)quicken;
@end
|
在Car类中定义了两个属性,以及一些方法
Car.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//
// Car.m
// 06_ExtendDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Car.h"
@implementation Car
- (void)setBrand:(NSString *)brand{
_brand = brand;
}
- (void)setColor:(NSString *)color{
_color = color;
}
- (void)brake{
NSLog(@ "刹车" );
}
- (void)quicken{
NSLog(@ "加速" );
}
@end
|
方法的实现
在来看一下子类:
Taxi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//
// Taxi.h
// 06_ExtendDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Car.h"
@interface Taxi : Car{
NSString *_company; //所属公司
}
//打印发票
- (void)printTick;
@end
|
看到Taxi类继承了父类Car,这里需要导入父类的头文件,然后在Taxi类中多了一个属性和方法
Taxi.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//
// Taxi.m
// 06_ExtendDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Taxi.h"
@implementation Taxi
- (void)printTick{
[ super brake];
[self brake];
NSLog(@ "%@出租车打印了发票,公司为:%@,颜色为:%@" ,_brand,_company,_color);
}
@end
|
对方法的实现,这里我们看到实现文件中是不需要导入父类Car的头文件的,因为可以认为,Taxi.h头文件中已经包含了Car的头文件了。而且,这里可以使用super关键字来调用父类的方法,同时这里我们也是可以用self关键字来调用,这里看到其实这两种方式调用的效果是一样的,当我们在子类重新实现brake方法的时候(Java中的重写概念),那么这时候super关键字调用的还是父类的方法,而self调用的就是重写之后的brake方法了。同样,我们也是可以使用父类中的属性。
再看一下另外一个子类:
Truck.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//
// Truck.h
// 06_ExtendDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Car.h"
//卡车类继承Car
@interface Truck : Car{
float _maxWeight; //最大载货量
}
//覆盖父类的方法brake
//优先调用子类的方法
- (void)brake;
- (void)unload;
@end
|
这里就自己定义了一个brake方法,这时候就会覆盖父类中的brake方法了。
Truck.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//
// Truck.m
// 06_ExtendDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Truck.h"
@implementation Truck
- (void)brake{
[ super brake];
NSLog(@ "Truck类中的brake方法" );
}
- (void)unload{
[ super brake]; //调用父类的方法
[self brake]; //也是可以的
NSLog(@ "%@的卡车卸货了,载货量:%.2f,汽车的颜色:%@" ,_brand,_maxWeight,_color);
}
@end
|
这里就可以看到,我们会在brake方法中调用一下父类的brake方法,然后在实现我们自己的逻辑代码。
好了,继承就说这么多了,其实封装和继承两个特性没什么难度的,很容易理解的,下面在来看一下最后一个特性:多态
三、多态
多态对于面向对象思想来说,个人感觉是真的很重要,他对以后的编写代码的优雅方式也是起到很重要的作用,其实现在很多设计模式中大部分都是用到了多态的特性,Java中的多态特性用起来很是方便的,但是C++中就很难用了,其实多态说白了就是:定义类型和实际类型,一般是基于接口的形式实现的,不多说了,直接看例子吧:
打印机的例子
抽象的打印机类Printer
Printer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//
// Printer.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import
@interface Printer : NSObject
- (void) print;
@end
|
就是一个简单的方法print
Printer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//
// Printer.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Printer.h"
@implementation Printer
- (void)print{
NSLog(@ "打印机打印纸张" );
}
@end
|
实现也是很简单的
下面来看一下具体的子类
ColorPrinter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//
// ColorPrinter.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Printer.h"
//修改父类的打印行为
@interface ColorPrinter : Printer
- (void)print;
@end
|
ColorPrinter.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//
// ColorPrinter.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "ColorPrinter.h"
@implementation ColorPrinter
- (void)print{
NSLog(@ "彩色打印机" );
}
@end
|
在看一下另外一个子类
BlackPrinter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
BlackPrinter.m
//
// BlackPrinter.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "BlackPrinter.h"
@implementation BlackPrinter
- (void)print{
NSLog(@ "黑白打印机" );
}
@end
|
这里我们在定义一个Person类,用来操作具体的打印机
Person.h
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
|
Person.m
//
// Person.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Person.h"
@implementation Person
/*
- (void) printWithColor:(ColorPrinter *)colorPrint{
[colorPrint print];
}
- (void) printWithBlack:(BlackPrinter *)blackPrint{
[blackPrint print];
}
*/
- (void) doPrint:(Printer *)printer{
[printer print];
}
@end
|
再来看一下测试代码:
main.m
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
45
|
//
// main.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import
#import "Person.h"
#import "BlackPrinter.h"
#import "ColorPrinter.h"
int main(int argc, const charchar * argv[]) {
@autoreleasepool {
Person *person =[[Person alloc] init];
ColorPrinter *colorPrint = [[ColorPrinter alloc] init];
BlackPrinter *blackPrint = [[BlackPrinter alloc] init];
//多态的定义
/*
Printer *p1 = [[ColorPrinter alloc] init];
Printer *p2 = [[BlackPrinter alloc] init];
[person doPrint:p1];
[person doPrint:p2];
*/
//通过控制台输入的命令来控制使用哪个打印机
int cmd;
do {
scanf( "%d" ,&cmd);
if (cmd == 1){
[person doPrint:colorPrint];
} else if (cmd == 2){
[person doPrint:blackPrint];
}
} while (1);
}
return 0;
}
|
下面就来详细讲解一下多态的好处
上面的例子是一个彩色打印机和黑白打印机这两种打印机,然后Person类中有一个操作打印的方法,当然这个方法是需要打印机对象的,如果不用多态机制实现的话(Person.h中注释的代码部分),就是给两种打印机单独定义个操作的方法,然后在Person.m(代码中注释的部分)中用具体的打印机对象进行操作,在main.m文件中,我们看到,当Person需要使用哪个打印机的时候,就去调用指定的方法:
1
2
|
[person printWithBlack:blackPrint]; //调用黑白打印机
[person printWithColor:colorPrint]; //调用彩色打印机
|
这种设计就不好了,为什么呢?假如现在又有一种打印机,那么我们还需要在Person.h中定义一种操作这种打印机的方法,那么后续如果在添加新的打印机呢?还在添加方法吗?那么Person.h文件就会变得很臃肿。所以这时候多态就体现到好处了,使用父类类型,在Person.h中定义一个方法就可以了:
1
|
- (void) doPrint:(Printer *)printer;
|
这里看到了,这个方法的参数类型就是父类的类型,这就是多态,定义类型为父类类型,实际类型为子类类型
1
2
3
|
- (void) doPrint:(Printer *)printer{
[printer print];
}
|
这里调用print方法,就是传递进来的实际类型的print方法。
1
2
3
4
5
|
Printer *p1 = [[ColorPrinter alloc] init];
Printer *p2 = [[BlackPrinter alloc] init];
[person doPrint:p1];
[person doPrint:p2];
|
这里的p1,p2表面上的类型是Printer,但是实际类型是子类类型,所以会调用他们自己对应的print方法。
从上面的例子中我们就可以看到多态的特新很是重要,当然也是三大特性中比较难理解的,但是在coding的过程中,用多了就自然理解了,没必要去刻意的理解。
公众号:CocoaChina
29
相关资讯
- 如何在iOS上创建矢量图形
- iOS开发--处理不等高TableViewCell的小花招
- 小白如何晋级入门级iOS开发者
- iOS runtime实战应用:成员变量和属性
- 解决3D Touch导致系统相册崩溃的问题
- iOS开发编码建议与编程经验(持续更新中)
- iOS开发调试技巧总结(持续更新中)
- iOS开发-CALayer的探究应用
- Unrecognized Selector Sent to Instance问题
- 深入浅出-iOS函数式编程的实现 && 响应式编程概念
热门资讯
-
你真的了解iOS代理设计模式吗?
点击量29627
-
我是如何检测内存泄露的
点击量16272
-
iOS面试必看,最全梳理
点击量10875
-
iOS开发编码建议与编程经验(持续更新中)
点击量8664
-
Hello,服务端 Swift
点击量8017
-
移动端地图技术分享
点击量7488
-
iOS 9学习系列: ReplayKit框架入门
点击量7063
-
苹果发布Xcode 7.3,Swift更新至2.2版本
点击量6588
-
iOS开发调试技巧总结(持续更新中)
点击量6497
-
小白如何晋级入门级iOS开发者
点击量5716
综合评论
- 设置完后,qq连接一会就闪退了,
流星载梦评论了【指南】本地如何搭建IPv6环境测试你的APP...
- mark
Jiuaim评论了揭秘 iOS App Extension 开发 —...
- mark
小米12345评论了iOS复杂动画之抽丝剥茧(Objective-C ...
- good
江坤阳评论了源码推荐(05.13):OC版快速集成网易新闻顶部...
- 535754174 iOS开发 技术交流 ,大家共同学习共同成长
iOSsiRYu评论了iOS客户端公共WIFI解决方案...
- 走下神坛,再不开放就要被竞争对手干死了。。。
Immanito评论了iTunes Connect最新的六大特性...
- 那小编为啥不比比和老美程序员的待遇呢?
mengjijinsha评论了探讨:中国的程序员培训是不是有问题...
- 其实,他们想要的是,第一种人的技术,第二种人的工资开销
mengjijinsha评论了两种编程高手
- 其实,他们想要的是,第一种人的技术,第二种人的工资开销
mengjijinsha评论了两种编程高手
- 怎么给ZXOptionBarCell加了扩展touch方法 都编译不过
王飞评论了用Swift实现一个具有类似UITableView...
相关帖子
- 本地通知如何自定义时间?
- 链接问题吧
- 利用观察者模式,观察UIScrollView的位移变化值,怎么取出对应的值?
- 瞧一瞧看一看啦。Xcode8创建一个简单的项目什么都没干就报错!pod SDK也报错
- ijk视频集成到项目中,图片死也出不来...
- 视频全屏
- 用WKWebview如何禁止webview页面缩小放大?
- 接受商城/洗车/社交/直播等各行业app定制开发(提供源码)
- UICollectionView如何设置编辑状态
北京触控科技有限公司版权所有
©2016 Chukong Technologies,Inc.京ICP备 11006519号 京ICP证 100954号 京公网安备11010502020289 京网文[2012]0426-138号
转载于:https://www.cnblogs.com/iOS-mt/p/5601202.html
多态---父指针指向子类对象(父类引用指向子类对象)相关推荐
- 父类引用指向子类对象详解
父类引用指向子类对象 父类引用指向子类对象指的是: 例如父类Animal,子类Cat,Dog.其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类. Animal ani ...
- Java多态 父类引用指向子类对象
原文地址http://www.cnblogs.com/111testing/p/6880831.html Java多态的三个必要条件: 1. 继承 2. 子类重写父类方法 3. 父类引用指向子类对象 ...
- java子类引用指向父类对象_Java多态 父类引用指向子类对象
Java多态的三个必要条件: 1. 继承 2. 子类重写父类方法 3. 父类引用指向子类对象 然后看一个例子 输出结果为: 给出结论:Father c = new Child() 在c的 ...
- Java多态-如何理解父类引用指向子类对象
java多态,如何理解父类引用指向子类对象 要理解多态性,首先要知道什么是"向上转型". 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过 C ...
- java多态 成员访问特点(父类引用指向子类对象)
>父类 子类 package com.dareway.demo;public class Father {public String index="fatherLogo"; ...
- java父类引用子类_java多态,如何理解父类引用指向子类对象
要理解多态性,首先要知道什么是"向上转型". 转型是在继承的基础上而言的,继承是面向对象语言中,代码复用的一种机制,通过继承,子类可以复用父类的功能,如果父类不能满足当前子类的需求 ...
- 多态之父类引用指向子类对象
首先,这是多态的知识,多态有三要素: 继承 , 重写父类的方法 , 父类引用指向子类对象 以下是我对于多态的一些理解,如有不当,还请指正! 一,多态的概念与特征: 1.什么多态 多态是同一个行为具有多 ...
- 多态的理解(父类引用指向子类对象)
多态: 要有继承,方法的重写,父类引用指向子类对象 ?疑问:Animal cat = new Cat(); //向上转型. 父类引用指向子类对象,该引用不能再访问子类 ...
- java 父类引用子类对象_java多态,如何理解父类引用指向子类对象
java多态,如何理解父类引用指向子类对象 要理解多态性,首先要知道什么是"向上转型". 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过 C ...
- java多态父类引用指向子类对象为什么不能调用子类特有的方法?
java多态父类引用指向子类对象为什么不能调用子类特有的方法? 我们在学习java面向对象时都会发现当父类引用指向子类对象不能调用子类特有的方法 首先我们需要了解一下java多态的具体体现 1.一个对 ...
最新文章
- 问题集锦(52-53)
- 中小企业网站建设不妨试试快速建站
- 关于align=absmiddle的说明
- selenium webdriver(python)_selenium、webdriver及浏览器的关系及对应版本安装
- 如何处理CloudFoundry应用部署时遇到的254错误
- Android 系统(49)---Android获取窗口可视区域大小: getWindowVisibleDisplayFrame()
- 历法 —— 十二地支与二十八星宿
- python机器学习案例系列教程——集成学习(Bagging、Boosting、随机森林RF、AdaBoost、GBDT、xgboost)
- IT运维的五大基础知识
- 生成器模式(Builder)
- 网站被黑检测与网站被黑处理方法
- 常用中文字体的Unicode编码
- 使用面包板的一点小注意
- IT前沿技术之node.js篇一:Node.js与javascript
- 融360 D轮融资超10亿 平台型互联网金融价值凸显
- 同态加密中无符号数之间比较大小
- Socks代理是什么?PC端怎么使用Socks5代理?
- Knowledge Graph Embedding: A Survey of Approaches and Applications (2)
- 服装企业在实践中探索
- 山寨机需要规范,中国需要山寨机
热门文章
- 微信无法连接服务器501,微信成语猜猜看第501关BUG出现全是英文怎么过解决方法...
- 2018usnews计算机专业排名,2018年研究生计算机专业前50排名(美USNews版)
- 在spoc上安装linux系统,郁闷,HACMP的C-SPOC没办法用
- jdbc mysql查询显示图片_JDBC【向数据库中存入读取图片】
- ci框架 mysql_CodeIgniter (CI)框架中的数据库查询汇总
- u盘循环冗余能修复吗_古董修复能修复吗?-恩平 - 商业服务
- linux创建组并指定gid的命令,在Linux中用groupadd命令创建组:创建具有特定GID的组及系统组...
- android studio导入aar包,AndroidStudio导入本地aar文件
- linux top cpu核数查看,Linux怎么查看CPU核数?
- mysql timestamp 更新_[mysql] timestamp自动更新和初始化