1 编写交通工具程序

1.1 问题

本案例需要创建一个TRTransportation类,类中有一个方法叫print的方法,该方法默认输出 “显示交通工具信息”,这个类作为父类,派生出三个子类TRTaxi的士类、TRBus巴士类和TRBike 自行车类。TRTaxi的士类覆盖了父类的print方法,改成自己的输出,"交通工具为的士";TRBus巴士类覆盖了父类的print方法,改成自己的输出,"交通工具为巴士";TRBike 自行车类覆盖了父类的print方法,改成自己的输出,"交通工具为单车"。

在主程序中,创建三个交通工具,使用多态输出交通工具信息。

1.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义TRTransportation类

首先,在Day04工程中新添加TRTransportation.h文件,用于定义新的类TRTransportation。

代码如下所示:

 
  1. #import <Foundation/Foundation.h>
  2. @interface TRTRansportation : NSObject
  3. -(void)print;
  4. @end

在上述代码中,为TRTransportation类添加一个方法print,用于输出信息“显示交通工具信息”到控制台。

然后,在类TRTransportation的实现部分,即在TRTransportation.m文件中,添加print方法的实现。

代码如下所示:

 
  1. #import "TRTransportation.h"
  2. @implementation TRTRansportation
  3. -(void)print{
  4. NSLog(@"显示交通工具信息");
  5. }
  6. @end

步骤二:定义TRTaxi类

首先,在Day04工程中新添加TRTaxi.h文件,用于定义新的类TRTaxi。

代码如下所示:

  1. #import "TRTransportation.h"
  2. @interface TRTaxi : TRTRansportation
  3. @end

上述代码可以看出,TRTaxi类继承自父类TRTRansportation。TRTaxi类并没有声明自己的属性和方法。

然后,在类TRTaxi的实现部分,即在TRTaxi.m文件中,重写由父类TRTRansportation继承的print方法。

代码如下所示:

  1. #import "TRTaxi.h"
  2. @implementation TRTaxi
  3. -(void)print{
  4. NSLog(@"交通工具为的士");
  5. }
  6. @end

步骤三:定义TRBus类

首先,在Day04工程中新添加TRBus.h文件,用于定义新的类TRBus。

代码如下所示:

  1. #import "TRTransportation.h"
  2. @interface TRBus : TRTRansportation
  3. @end

上述代码可以看出,TRBus类继承自父类TRTRansportation。TRBus类并没有声明自己的属性和方法。

然后,在类TRBus的实现部分,即在TRBus.m文件中,重写由父类TRTRansportation继承的print方法。

代码如下所示:

  1. #import "TRBus.h"
  2. @implementation TRBus
  3. -(void)print{
  4. NSLog(@"交通工具为巴士");
  5. }
  6. @end

步骤四:定义TRBike类

首先,在Day04工程中新添加TRBike.h文件,用于定义新的类TRBike。

代码如下所示:

  1. #import "TRTransportation.h"
  2. @interface TRBike : TRTRansportation
  3. @end

上述代码可以看出,TRBike类继承自父类TRTRansportation。TRBike类并没有声明自己的属性和方法。

然后,在类TRBike的实现部分,即在TRBike.m文件中,重写由父类TRTRansportation继承的print方法。

代码如下所示:

  1. #import "TRBike.h"
  2. @implementation TRBike
  3. -(void)print{
  4. NSLog(@"交通工具为单车");
  5. }
  6. @end

步骤五:在主程序中定义以上各类的对象

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRTransportation.h"
  3. #import "TRTaxi.h"
  4. #import "TRBus.h"
  5. #import "TRBike.h"
  6. int main(int argc, const char * argv[])
  7. {
  8. @autoreleasepool {
  9. // insert code here...
  10. TRTRansportation* tran = [[TRTRansportation alloc] init];
  11. [tran print];
  12. TRTRansportation* tran1 = [[TRBus alloc] init];
  13. [tran1 print];
  14. TRTRansportation* tran2 = [[TRTaxi alloc] init];
  15. [tran2 print];
  16. TRTRansportation* tran3 = [[TRBike alloc] init];
  17. [tran3 print];
  18. }
  19. return 0;
  20. }

在上述代码中,以下代码:

  1. TRTRansportation* tran = [[TRTRansportation alloc] init];
  2. [tran print];

定义了一个TRTRansportation类的对象tran,并向对象tran发送print消息,以在控制台上输出“显示交通工具信息”。

在上述代码中,以下代码:

  1. TRTRansportation* tran1 = [[TRBus alloc] init];
  2. [tran1 print];

定义了一个TRTRansportation类类型的指针tran1,用它指向TRBus类的对象,这是允许的。在多态的概念中,允许用父类的指针指向派生类的对象。但此时只能向该指针指向的派生类对象发送父类中已有的消息,派生类中自定义的父类中没有的消息不能被发送,同时发送的这个消息将调用派生类中重写的函数。如上述代码中,向指向派生类对象的父类指针tran1发送父类中已经定义的print消息,调用的是派生类中重写的函数,所以在控制台上输出“交通工具为巴士”。

在上述代码中,以下代码:

  1. TRTRansportation* tran2 = [[TRTaxi alloc] init];
  2. [tran2 print];

定义了一个TRTRansportation类类型的指针tran2,用它指向TRTaxi类的对象,向该指针tran2发送父类中已经定义的print消息,调用的是派生类中重写的函数,所以在控制台上输出“交通工具为的士”。

在上述代码中,以下代码:

  1. TRTRansportation* tran3 = [[TRBike alloc] init];
  2. [tran3 print];

定义了一个TRTRansportation类类型的指针tran3,用它指向TRBike类的对象,向该指针tran3发送父类中已经定义的print消息,调用的是派生类中重写的函数,所以在控制台上输出“交通工具为单车”。

1.3 完整代码

本案例中,类TRTransportation声明,即TRTransportation.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface TRTRansportation : NSObject
  3. -(void)print;
  4. @end

类TRTransportation实现,即TRTransportation.m文件,完整代码如下所示:

  1. #import "TRTransportation.h"
  2. @implementation TRTRansportation
  3. -(void)print{
  4. NSLog(@"显示交通工具信息");
  5. }
  6. @end

本案例中,类TRTaxi声明,即TRTaxi.h文件,完整代码如下所示:

  1. #import "TRTransportation.h"
  2. @interface TRTaxi : TRTRansportation
  3. @end

类TRTaxi实现,即TRTaxi.m文件,完整代码如下所示:

  1. #import "TRTaxi.h"
  2. @implementation TRTaxi
  3. -(void)print{
  4. NSLog(@"交通工具为的士");
  5. }
  6. @end

本案例中,类TRBus声明,即TRBus.h文件,完整代码如下所示:

  1. #import "TRTransportation.h"
  2. @interface TRBus : TRTRansportation
  3. @end

类TRBus实现,即TRBus.m文件,完整代码如下所示:

  1. #import "TRBus.h"
  2. @implementation TRBus
  3. -(void)print{
  4. NSLog(@"交通工具为巴士");
  5. }
  6. @end

本案例中,类TRBike声明,即TRBike.h文件,完整代码如下所示:

  1. #import "TRTransportation.h"
  2. @interface TRBike : TRTRansportation
  3. @end

类TRBike实现,即TRBike.m文件,完整代码如下所示:

  1. #import "TRBike.h"
  2. @implementation TRBike
  3. -(void)print{
  4. NSLog(@"交通工具为单车");
  5. }
  6. @end

主程序,即main.m,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRTransportation.h"
  3. #import "TRTaxi.h"
  4. #import "TRBus.h"
  5. #import "TRBike.h"
  6. int main(int argc, const char * argv[])
  7. {
  8. @autoreleasepool {
  9. // insert code here...
  10. TRTRansportation* tran = [[TRTRansportation alloc] init];
  11. [tran print];
  12. TRTRansportation* tran1 = [[TRBus alloc] init];
  13. [tran1 print];
  14. TRTRansportation* tran2 = [[TRTaxi alloc] init];
  15. [tran2 print];
  16. TRTRansportation* tran3 = [[TRBike alloc] init];
  17. [tran3 print];
  18. }
  19. return 0;
  20. }

2 编写SuperMan类

2.1 问题

本案例需要定义两个协议,一个是TRPerson,它定义了一个方法job;另一个是TRFly,它定义了一个方法fly。创建一个SuperMan类,采用以上两个协议,使该类具有飞翔和工作的能力。

2.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义协议TRPerson

首先,在Day04-2工程中新添加TRPerson.h文件,用于定义新的协议TRPerson。

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @protocol TRPerson <NSObject>
  3. -(void)job;
  4. @end

在上述代码中,定义了一个协议TRPerson,在协议中有一个方法job的声明,表示采纳这个协议的类将具有工作的能力。该协议继承自NSObject。

步骤二:定义协议TRFly

首先,在Day04-2工程中新添加TRFly.h文件,用于定义新的协议TRFly。

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @protocol TRFly <NSObject>
  3. -(void)fly;
  4. @end

在上述代码中,定义了一个协议TRFly,在协议中有一个方法fly的声明,表示采纳这个协议的类将具有飞翔的能力。该协议继承自NSObject。

步骤三:定义SuperMan类

首先,在Day04-2工程中新添加SuperMan.h文件,用于定义新的类SuperMan。

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRFly.h"
  3. #import "TRPerson.h"
  4. @interface SuperMan : NSObject<TRFly,TRPerson>
  5. @end

上述代码可以看出,SuperMan类采纳了两个协议,一个是TRFly,另一个是TRPerson。SuperMan类并没有声明自己的属性和方法。

然后,在类SuperMan的实现部分,即在SuperMan.m文件中,对采纳的两个协议中的方法进行实现。当一个类采纳了某个协议后,在类的实现部分必须写出协议中声明的方法的实现。

代码如下所示:

  1. #import "SuperMan.h"
  2. @implementation SuperMan
  3. -(void)fly{
  4. NSLog(@"具有飞行的能力");
  5. }
  6. -(void)job{
  7. NSLog(@"具有了工作的能力");
  8. }
  9. @end

步骤四:在主程序中使用SuperMan类

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRPerson.h"
  3. #import "TRFly.h"
  4. #import "SuperMan.h"
  5. int main(int argc, const char * argv[])
  6. {
  7. @autoreleasepool {
  8. // insert code here...
  9. id<TRFly,TRPerson> sMan = [[SuperMan alloc]init];
  10. [sMan fly];
  11. [sMan job];
  12. }
  13. return 0;
  14. }

在上述代码中,以下代码:

  1. id<TRFly,TRPerson> sMan = [[SuperMan alloc]init];

定义了一个id类型的指针sMan,并将指针sMan指向SuperMan类的对象。该id类型的指针由于进行了<TRFly,TRPerson>协议限定,所以指针只能调用SuperMan类中实现的TRFly协议和TRPerson协议声明的方法。

在上述代码中,以下代码:

  1. [sMan fly];
  2. [sMan job];

分别向id类型的指针发送fly消息和job消息,调用SuperMan类中的方法实现。

2.3 完整代码

本案例中,协议TRPerson声明,即TRPerson.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @protocol TRPerson <NSObject>
  3. -(void)job;
  4. @end

本案例中,协议TRFly声明,即TRFly.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @protocol TRFly <NSObject>
  3. -(void)fly;
  4. @end

本案例中,类SuperMan声明,即SuperMan.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRFly.h"
  3. #import "TRPerson.h"
  4. @interface SuperMan : NSObject<TRFly,TRPerson>
  5. @end

类SuperMan实现,即SuperMan.m文件,完整代码如下所示:

  1. #import "SuperMan.h"
  2. @implementation SuperMan
  3. -(void)fly{
  4. NSLog(@"具有飞行的能力");
  5. }
  6. -(void)job{
  7. NSLog(@"具有了工作的能力");
  8. }
  9. @end

主程序,即main.m,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "TRPerson.h"
  3. #import "TRFly.h"
  4. #import "SuperMan.h"
  5. int main(int argc, const char * argv[])
  6. {
  7. @autoreleasepool {
  8. // insert code here...
  9. id<TRFly,TRPerson> sMan = [[SuperMan alloc]init];
  10. [sMan fly];
  11. [sMan job];
  12. }
  13. return 0;
  14. }

Objective-C--- 多态 、 协议的更多相关文章

  1. Objective中的协议(Protocol)

    Objective中的协议(Protocol) 作用: 专门用来声明一大堆方法. (不能声明属性,也不能实现方法,只能用来写方法的声明). 只要某个类遵守了这个协议.就相当于拥有这个协议中的所有的方法 ...

  2. Objective C多态

    面向对象的封装的三个基本特征是.继承和多态. 包是一组简单的数据结构和定义相关的操作在上面的其合并成一个类,继承1种亲子关系,子类能够拥有父类定的成员变量.属性以及方法. 多态就是指父类中定义的成员变 ...

  3. Objective - C 之协议

    一.创建方法: 二.实现过程: 1.遵循协议: @protocol NurseWorkingProtocol <NSObject>   //<> 表示遵守协议,创建时就有(Nu ...

  4. Objective-C中的类目,延展,协议

    Objective-C中的类目(Category),延展(Extension),协议(Protocol)这些名词看起来挺牛的,瞬间感觉OC好高大上.在其他OOP语言中就没见过这些名词,刚看到这三个名词 ...

  5. Xcode 常用编译选项设置

    Xcode 常用编译选项设置 在xcconfig文件中指定即可. 用标准库连接 LINK_WITH_STANDARD_LIBRARIES = YES如果激活此设置,那么编译器在链接过程中会自动使用通过 ...

  6. 小程序多端框架全面测评:chameleon、Taro、uni-app、mpvue、WePY

    摘要: 微信小程序开发技巧. 作者:coldsnap 原文:小程序多端框架全面测评 Fundebug经授权转载,版权归原作者所有. 最近前端届多端框架频出,相信很多有代码多端运行需求的开发者都会产生一 ...

  7. Clojure 哲学

    简单性.专心编程不受打扰(freedom to focus).给力(empowerment).一致性和明确性:Closure编程语言中几乎每一个元素的设计思想都是为了促成这些目标的实现. 学习一门新的 ...

  8. Automake

    Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...

  9. 五.OC基础--1.多态,2.类对象,3.点语法,4.@property&@synthesize,5.动态类型,内省(判断对象是否遵循特定的协议,以及是否可以响应特定的消息)

    五.OC基础--1.多态, 1. 多态概念,定义:多态就是某一类事物的多种形态: 表现形式: Animal *ani = [Dog new]; 多态条件:1.有继承关系 2.有方法的重写 2.多态代码 ...

  10. Python:多态、协议和鸭子类型

    多态 问起面向对象的三大特性,几乎每个人都能对答如流:封装.继承.多态.今天我们就要来说一说 Python 中的多态. 所谓多态:就是指一个类实例的相同方法在不同情形有不同表现形式.多态机制使具有不同 ...

随机推荐

  1. Octopus系列之如何让前台的js脚本变得灵活重用

    Octopus系列如何让前台的js脚本变得灵活,重用 方式1:ajax方式 方式2:form表单方式 面向对象的脚本封装 jQuery的封装 做Web开发的少不了前台Ajax的使用, 返回true:f ...

  2. HTTP 错误 500.22 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.NET 设置

    答案:在将WebDataHelper升级到VS2013是出现的这个错误,这个程序使用了URL重写的技术, 解决方法是:需要将重写的配置,迁移到system.webServer配置节中

  3. 二分图 最大权匹配 km算法

    这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最 ...

  4. ruby学习网站

    Ruby官方中文网(推荐): https://www.ruby-lang.org/zh_cn/ 国内非常不错的Ruby学习教程网站(推荐): http://www.yiibai.com/ruby Ru ...

  5. java 面向对象编程 --第十二章 JDK常用类

    1.  系统类 java.lang包   System类 sys.out;sys.exit;sys.gc; sys.currentTimeMillis();----得到从1970-01-01到当前时间 ...

  6. 计算excel列的名字

    #include <iostream> using namespace std; int main() {     unsigned int column;     cin>> ...

  7. sql插入多条数据的sql语句

    sql插入多条数据的sql语句 有三种方法:1.InSert Into <表名>(列名)Select <列名>From <源表名>如:INSERT INTO Ton ...

  8. NOIP2004 解题报告

    第一题:津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里, ...

  9. iOS9/iOS8界面对比 XCode7

    Xcde7 bate 无需开发这账号(99¥)可以调试程序 目前是测试版 iOS9/iOS8界面对比 (注:左边为iOS8界面,右边为iOS9界面.) 1.新字体 苹果在 iOS9 中使用旧金山字体取 ...

  10. AndroidStudio导入第三方开源库 --文件夹源码

    1 在已打开的项目中  File-New-ImportModule 选择开源项目中的 库所在文件夹比如 library文件夹 然后导入. 2 File-Project  Sructure  在Modu ...