OC 多态
2015-12-08 11:33
267 查看
多态
多态使用总结
(1)没有继承就没有多态
(2)代码的体现:父类类型的指针指向子类对象
(3)好处:如果函数方法参数中使用的是父类类型,则可以传入父类和子类对象,而不用再去定义多个函数来和相应的类进行匹配了。
(4)局限性:父类类型的变量不能直接调用子类特有的方法,如果必须要调用,则必须强制转换为子类特有的方法。
(5)其实多态说白了就是:定义类型和实际类型,一般是基于接口的形式实现的,不多说了,直接看例子吧:
打印机的例子
抽象的打印机类Printer
Printer.h
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// Printer.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Printer : NSObject
- (void) print;
@end
就是一个简单的方法print
Printer.m
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// 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
[java] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// BlackPrinter.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Printer.h"
@interface BlackPrinter : Printer
- (void)print;
@end
BlackPrinter.m
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// Person.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ColorPrinter.h"
#import "BlackPrinter.h"
//扩展性不高,当我们需要添加一个新的打印机的时候还要定义对应的一个方法
//所以这时候就可以使用多态技术了
@interface Person : NSObject{
NSString *_name;
}
//- (void) printWithColor:(ColorPrinter *)colorPrint;
//- (void) printWithBlack:(BlackPrinter *)blackPrint;
- (void) doPrint:(Printer *)printer;
@end
Person.m
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
//
// main.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
#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需要使用哪个打印机的时候,就去调用指定的方法:
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
[person printWithBlack:blackPrint];//调用黑白打印机
[person printWithColor:colorPrint];//调用彩色打印机
这种设计就不好了,为什么呢?假如现在又有一种打印机,那么我们还需要在Person.h中定义一种操作这种打印机的方法,那么后续如果在添加新的打印机呢?还在添加方法吗?那么Person.h文件就会变得很臃肿。所以这时候多态就体现到好处了,使用父类类型,在Person.h中定义一个方法就可以了:
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
- (void) doPrint:(Printer *)printer;
这里看到了,这个方法的参数类型就是父类的类型,这就是多态,定义类型为父类类型,实际类型为子类类型
[java] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
- (void) doPrint:(Printer *)printer{
[printer print];
}
这里调用print方法,就是传递进来的实际类型的print方法。
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
Printer *p1 = [[ColorPrinter alloc] init];
Printer *p2 = [[BlackPrinter alloc] init];
[person doPrint:p1];
[person doPrint:p2];
这里的p1,p2表面上的类型是Printer,但是实际类型是子类类型,所以会调用他们自己对应的print方法。
多态使用总结
(1)没有继承就没有多态
(2)代码的体现:父类类型的指针指向子类对象
(3)好处:如果函数方法参数中使用的是父类类型,则可以传入父类和子类对象,而不用再去定义多个函数来和相应的类进行匹配了。
(4)局限性:父类类型的变量不能直接调用子类特有的方法,如果必须要调用,则必须强制转换为子类特有的方法。
(5)其实多态说白了就是:定义类型和实际类型,一般是基于接口的形式实现的,不多说了,直接看例子吧:
打印机的例子
抽象的打印机类Printer
Printer.h
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// Printer.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Printer : NSObject
- (void) print;
@end
就是一个简单的方法print
Printer.m
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// 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
[java] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// BlackPrinter.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Printer.h"
@interface BlackPrinter : Printer
- (void)print;
@end
BlackPrinter.m
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// Person.h
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ColorPrinter.h"
#import "BlackPrinter.h"
//扩展性不高,当我们需要添加一个新的打印机的时候还要定义对应的一个方法
//所以这时候就可以使用多态技术了
@interface Person : NSObject{
NSString *_name;
}
//- (void) printWithColor:(ColorPrinter *)colorPrint;
//- (void) printWithBlack:(BlackPrinter *)blackPrint;
- (void) doPrint:(Printer *)printer;
@end
Person.m
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// 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
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//
// main.m
// 07_DynamicDemo
//
// Created by jiangwei on 14-10-11.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
#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需要使用哪个打印机的时候,就去调用指定的方法:
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
[person printWithBlack:blackPrint];//调用黑白打印机
[person printWithColor:colorPrint];//调用彩色打印机
这种设计就不好了,为什么呢?假如现在又有一种打印机,那么我们还需要在Person.h中定义一种操作这种打印机的方法,那么后续如果在添加新的打印机呢?还在添加方法吗?那么Person.h文件就会变得很臃肿。所以这时候多态就体现到好处了,使用父类类型,在Person.h中定义一个方法就可以了:
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
- (void) doPrint:(Printer *)printer;
这里看到了,这个方法的参数类型就是父类的类型,这就是多态,定义类型为父类类型,实际类型为子类类型
[java] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
- (void) doPrint:(Printer *)printer{
[printer print];
}
这里调用print方法,就是传递进来的实际类型的print方法。
[objc] view plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
Printer *p1 = [[ColorPrinter alloc] init];
Printer *p2 = [[BlackPrinter alloc] init];
[person doPrint:p1];
[person doPrint:p2];
这里的p1,p2表面上的类型是Printer,但是实际类型是子类类型,所以会调用他们自己对应的print方法。
#import <Foundation/Foundation.h> /* 多态 1.没有继承就没有多态 2.代码的体现:父类类型的指针指向子类对象 3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象 4.局限性: 1> 父类类型的变量 不能 直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法 */ // 动物 @interface Animal : NSObject - (void)eat; @end @implementation Animal - (void)eat { NSLog(@"Animal-吃东西----"); } @end // 狗 @interface Dog : Animal - (void)run; @end @implementation Dog - (void)run { NSLog(@"Dog---跑起来"); } - (void)eat { NSLog(@"Dog-吃东西----"); } @end // 猫 @interface Cat : Animal @end @implementation Cat - (void)eat { NSLog(@"Cat-吃东西----"); } @end // 这个函数是专门用来喂动画 //void feed(Dog *d) //{ // [d eat]; //} // //void feed2(Cat *c) //{ // [c eat]; //} // // 如果参数中使用的是父类类型,可以传入父类、子类对象 void feed(Animal *a) { [a eat]; } int main() { // NSString *d = [Cat new]; // [d eat]; /* Animal *aa = [Dog new]; // 多态的局限性:父类类型的变量 不能 用来调用子类的方法 //[aa run]; // 将aa转为Dog *类型的变量 Dog *dd = (Dog *)aa; [dd run]; */ //Dog *d = [Dog new]; //[d run]; /* Animal *aa = [Animal new]; feed(aa); Dog *dd = [Dog new]; feed(dd); Cat *cc = [Cat new]; feed(cc); */ /* // NSString *s = [Cat new]; Animal *c = [Cat new]; NSObject *n = [Dog new]; NSObject *n2 = [Animal new]; // 多种形态 //Dog *d = [Dog new]; // Dog类型 // 多态:父类指针指向子类对象 Animal *a = [Dog new]; // 调用方法时会检测对象的真实形象 [a eat]; */ return 0; }
相关文章推荐
- android自定义dialog实现app换肤功能
- Android ADB常用命令总结
- EzLaze III
- 我的工具太少了之Android无限轮播图片,最后一张过度动画很重要
- LeetCode 215 Kth Largest Element in an Array
- iOS 使用collectionView实现无线轮播
- 如何走技术路线的研究生论文?
- Windows 上安装docker
- Excel公式不计算
- 函数的重载
- Java下载文件
- 堆/栈
- 强引用,软引用,弱引用,虚引用
- Android - 文件读写操作 总结
- Android:Layout_weight的深刻理解(转载于51CTO)
- Charles抓包监测和网络知识梳理
- 【Struts2】(7)ModelDriven和类型转换器
- SuperMap中动画模型制作详解
- ccf认证--201509-3
- 关于解决spring 只能跳转到.jsp 不能跳转到.html的问题