SlideShare a Scribd company logo
1 of 10
Download to read offline
从 C&C++过渡到 Objective-C

序:

对于已经熟悉 C++的人来说,从事 iPhone 开发一开始就陷入过多的 Objective-C 的细节可

能并非好事。




我们希望可以更加关注于 iPhone 开发特有的东西,快速上手。




下面这些内容可以帮助 C++程序员快速获得 Objective-C 的基本知识,并开始编写和阅读

iPhone 程序,如果在读别人的程序时,有些语法搞不懂,可以翻查我前面发的那本电子书

《    <Cocoa      入     门     ---   使     用     Objective-C>    英     文    版    》

(http://www.weiphone.com/thread-119791-1-1.html),把其作为参考手册用。




以 下 内 容 均 整 理 / 翻 译 自 《 iPhone                 Open   Application   Development 》

(http://www.weiphone.com/thread-119662-1-1.html)




编/译者: yangqiang.alan@gmail.com




1、消息

你应该注意的第一件事情就是 Objective-C 中大量使用了中括号。在 Objective-C 中,方法

不是使用传统形式(C/C++的语法形式)“调用”的;代替的是,“方法调用”变成了“消息

发送”。与此类似,“方法返回”,变成了“消息响应”。在 C 中,在调用方法之前必须预先

将其定义好;而 Objective-C 的消息风格,允许开发者在运行时动态创建方法和消息。这样
做的负面影响就是:完全允许向一个对象发送一个不可能返回的消息,这将导致异常,进而

可能让程序崩溃。

这里有一个对象 myWidget,一个消息可以被发送到它的 powerOn 方法上,像这样:

returnValue = [ myWidget powerOn ];

如果用 C++做同样的事情,则像这样:

returnValue = myWidget->powerOn();

C 则会在其扁平的名字空间上声明一个函数:

returnValue = widget_powerOn(myWidget);

只要一个对象可以接收,就可以向其传递参数。下面的例子调用了一个 setSpeed 方法,并

传递了两个参数:

returnValue = [ myWidget setSpeed: 10.0 withMass: 33.0 ];

注意,在这个消息中,第二个参数使用了显式名称(explicitly named)。这就允许声明多个具

有相同名称和类型的方法——即多态。

returnValue = [ myWidget setSpeed: 10.0 withMass: 33.0 ];

returnValue = [ myWidget setSpeed: 10.0 withGyroscope: 10.0 ];




2、类与方法声明

尽管可以在 Objective-C 中定义 C++的类,但最好能善用 Objective-C 自己的对象和特性。

Objective-C 中有接口的概念。在标准 C++中,类是结构,而类的变量和方法是被包含在结

构中的。Objective-C 中,把类的变量放在 one part of the class 中,方法放在另一部分中。

Objective-C 要求把 interface 声明在其自己的代码块中(in its own code block),称为

@interface;而其实现则定义在@implementation 代码块中。方法自身的构造跟 Smalltalk
很像,看其来跟 C 非常不同。

我们的组件(widget)的 interface 是下面这样的,放在一个 MyWidget.h 文件中。

#import <Foundation/Foundation.h>




@interface MyWidget : BaseWidget

{

     BOOL isPoweredOn;

     @private float speed;

     @protected float mass;

     @protected float gyroscope;

}

+ (id)alloc;

+ (BOOL)needsBatteries;

- (BOOL)powerOn;

- (void)setSpeed:(float)_speed;

- (void)setSpeed:(float)_speed withMass:(float)_mass;

- (void)setSpeed:(float)_speed withGyroscope:(float)_gyroscope;

@end

在下面的小节中会详细解释这个文件中的重要语义元素。




2.1、Import

使用预处理指令#import 代替传统的#include 指令(尽管#include 还是可以使用的)。使用
#import 的一个好处就是:它内建的逻辑可以保证相同的资源不会被包含多于一次。这就可

以避免像在 C 代码中那样,使用这样的宏:

#ifndef _MYWIDGET_H

#define _MYWIDGET_H

...

#endif




2.2、interface 声明

使用@interface 语句再跟上接口名和基类(如果有基类的话),来声明一个接口。此代码块使

用@end 语句结束。




2.3、方法

方法声明放在花括号结构的外面。+号表示这是一个静态方法,而-号声明这个方法是一个实

例方法。可以使用 MyWidget 类的引用直接调用 alloc 方法(分配一个新对象),而 MyWidget

类的实例方法(比如 needsBatteries 和 powerOn),就通过 alloc 返回的类实例来调用。

方法声明的每个参数,都使用数据类型、局部变量名和一个可选的外部变量名(external

variable name)来表示。外部变量名的例子就是上面程序中的 withMass 和 withGyroscope。

方法调用者在调用方法时,使用外部变量名;但在方法内部,则使用局部变量名来引用这个

参数。这样,setSpeed 方法就使用局部变量_mass 来获取传递进来的 withMass 的值。

如果在声明中没有提供外部变量名,则调用者只会使用一个冒号来引用这个变量,比

如 :10.0。
3、实现

Objective-C 源文件的后缀是.m。前面小节中 widget 类的骨架实现(skeletion implementation)

如下,放在一个 MyWidget.m 文件中。

#import "MyWidget.h"




@implementation MyWidget




+ (id)alloc {

}




+ (BOOL)needsBatteries {

     return YES;

}




- (BOOL)powerOn {

     isPoweredOn = YES;

     return YES;

}




- (void)setSpeed:(float)_speed {

     speed = _speed;

}
- (void)setSpeed:(float)_speed withMass:(float)_mass {

    speed = _speed;

    mass = _mass;

}




- (void)setSpeed:(float)_speed withGyroscope:(float)_gyroscope {

    speed = _speed;

    gyroscope = _gyroscope;

}

@end




就好像接口放在它自己的代码块中一样,实现放在由@implementation 语句开始、@end

语句结束的代码块中。在 C++中,使用 m_作为成员变量名的前缀,是一同常见的做法。而

Objective-C 中,局部变量名使用下划线作为前缀,通过外部变量名,向别人提供可读的变

量名称。




4、Category

Objective-C 向面向对象编程中增加了一个新的元素:称为 category。Category 被设计用来

解决这样的问题:基类被认为是脆弱的,应该避免对其进行看起来无害的改变,因为这样可

能会破坏更加复杂的派生类。当一个程序增长到特定的规模时,开发者经常害怕去触摸那个

较小的基类,因为如果不对整个应用程序详细审查,就无法确定:对基类的改变是否安全。
Category 提供了一个机制,来为基类增加功能,而不影响其他的对象。

category 类可以增加和替换一些基类的方法。这可以在不重新编译基类、甚至不必访问基

类源代码的情况下做到。Category 允许在有限的范围内(within a limited scope)对基类进行

扩展(expanded),那么任何使用基类(而非 category 类)的对象,将继续看到原始的版本。

从开发的角度看,这使得你更容易改进其他开发者所写的类。在运行时,使用 category 的

代码部分将看到这个类的新版本,而直接使用基类的代码则只看到原始版本。

组件工厂发布了一种新型的组件,它可以在太空中飞行,但是如果改变它们的基类,将可能

破坏已经存在的应用。通过构建一个 category,使用 MyWidget 基类的应用程序将继续看见

这个原始类;而新的太空应用将使用 category。下面的例子在已经存在的 MyWidget 基类上

构建了一个新的 category,名为 MySpaceWidget。因为我们需要在太空中爆炸的能力,所

以增加了一个名为 selfDestruct 的方法。这个 category 还用自己的方法替换了已经存在的

powerOn 方法。对比一下:这里使用了圆括号包含 MySpaceWidget,来定义 category;而

在上面的例子中使用的是冒号来定义继承。

#import "MyWidget.h"




@interface MyWidget (MySpaceWidget)

- (void)selfDestruct;

- (BOOL)powerOn;

@end

下面是该 category 的实现:

#import "MySpaceWidget.h"
@implementation MyWidget (MySpaceWidget)




- (void)selfDestruct {

    isPoweredOn = 0;

    speed = 1000.0;

    mass = 0;

}




- (BOOL)powerOn {

    if (speed == 0) {

         isPoweredOn = YES;

         return YES;

    }




    /* Don't power on if the spaceship is moving */

    return NO;

}

@end




5、Pose(伪装)

在 Objective-C 中,子类对象可以伪装成其父类(pose as one of its superclasses),替换父

类对象接收所有的消息。这跟 overriding(重写)很像,但 overriding 只能重写整个类,而非
单个方法。在 Pose 类中,不能声明任何新成员变量,但可以重写或替换已经存在的方法。

Pose 跟 Category 有点相似,它们都允许开发者在运行时扩展一个已经存在的类(augment

an existing class at runtime)。

在前面的例子里,创建了一些机械组件类(mechanical widget classes)。随后,在定义了所

有这些组件之后,发现了永久能源。这就允许很多新的组件成为自治的了,然而老的组件仍

然需要电池。因为自治组件拥有非常庞大的不同代码,所以派生了一个名为

MyAutonomousWidget 的类,来重写所有需要改变的功能(比如静态的 needsBatteries 方

法)。

#import <Foundation/Foundation.h>

#import "MyWidget.h"

@interface MyAutonomousWidget : MyWidget

{




}

+ (BOOL)needsBatteries;

@end




#import "MyAutonomousWidget.h"

@implementation MyAutonomousWidget

+ (BOOL)needsBatteries {

    return NO;

}
@end




自治类不是改变所有已经存在的代码,而是可以简单的伪装成一个组件类。在主程序或其他

高阶(high-level)方法中调用 class_poseAs 方法,从而达到此目的:

  MyAutonomousWidget *myAutoWidget = [ MyAutonomousWidget alloc ];

  MyWidget *myWidget = [ MyWidget alloc ];

  class_poseAs(myAutoWidget, myWidget);

从这里开始,我们放在 pose 类中的任何其他方法(给自治设备用的)都将伪装成原来的基类

被使用。

More Related Content

Viewers also liked

Presentatie Opdracht 3
Presentatie Opdracht 3Presentatie Opdracht 3
Presentatie Opdracht 3rachelensimone
 
Rfs Mortgage Inspections Property Preservation Evaluation Services
Rfs Mortgage Inspections Property Preservation Evaluation ServicesRfs Mortgage Inspections Property Preservation Evaluation Services
Rfs Mortgage Inspections Property Preservation Evaluation ServicescekIII
 
Rfs Ppt Field Calls
Rfs Ppt Field CallsRfs Ppt Field Calls
Rfs Ppt Field CallscekIII
 
Grooming Day
Grooming DayGrooming Day
Grooming DayChewie
 
IcyBlaze学习文化从阅读开始
IcyBlaze学习文化从阅读开始IcyBlaze学习文化从阅读开始
IcyBlaze学习文化从阅读开始GARNETT2183
 
Anna Modelling
Anna ModellingAnna Modelling
Anna ModellingChewie
 
踢猫效应
踢猫效应踢猫效应
踢猫效应zhao yue
 
Tugas Akhir Semester I
Tugas Akhir Semester ITugas Akhir Semester I
Tugas Akhir Semester IEvi Susita
 
Lori's ETEC 442 Tech Timeline
Lori's ETEC 442 Tech TimelineLori's ETEC 442 Tech Timeline
Lori's ETEC 442 Tech Timelinelorinaka555
 

Viewers also liked (17)

QuickLook Guide
QuickLook GuideQuickLook Guide
QuickLook Guide
 
Presentatie Opdracht 3
Presentatie Opdracht 3Presentatie Opdracht 3
Presentatie Opdracht 3
 
Rfs Mortgage Inspections Property Preservation Evaluation Services
Rfs Mortgage Inspections Property Preservation Evaluation ServicesRfs Mortgage Inspections Property Preservation Evaluation Services
Rfs Mortgage Inspections Property Preservation Evaluation Services
 
Rfs Ppt Field Calls
Rfs Ppt Field CallsRfs Ppt Field Calls
Rfs Ppt Field Calls
 
Grooming Day
Grooming DayGrooming Day
Grooming Day
 
Lexi
LexiLexi
Lexi
 
Presentation1
Presentation1Presentation1
Presentation1
 
111
111111
111
 
Test 2
Test 2Test 2
Test 2
 
111
111111
111
 
IcyBlaze学习文化从阅读开始
IcyBlaze学习文化从阅读开始IcyBlaze学习文化从阅读开始
IcyBlaze学习文化从阅读开始
 
Anna Modelling
Anna ModellingAnna Modelling
Anna Modelling
 
踢猫效应
踢猫效应踢猫效应
踢猫效应
 
TUGAS LOGIKA
TUGAS LOGIKATUGAS LOGIKA
TUGAS LOGIKA
 
Tugas Akhir Semester I
Tugas Akhir Semester ITugas Akhir Semester I
Tugas Akhir Semester I
 
Lori's ETEC 442 Tech Timeline
Lori's ETEC 442 Tech TimelineLori's ETEC 442 Tech Timeline
Lori's ETEC 442 Tech Timeline
 
10 Negotiation Tips
10 Negotiation Tips10 Negotiation Tips
10 Negotiation Tips
 

Similar to 111

第1讲 开始编写程序
第1讲 开始编写程序第1讲 开始编写程序
第1讲 开始编写程序ruandao
 
Programming in Objective-C
Programming in Objective-CProgramming in Objective-C
Programming in Objective-CRyan Chung
 
Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)babyyellow li
 
Xcode开发员入门导引
Xcode开发员入门导引Xcode开发员入门导引
Xcode开发员入门导引Sophia Lindsey
 
Clipper@datacon.2019.tw
Clipper@datacon.2019.twClipper@datacon.2019.tw
Clipper@datacon.2019.twWei-Yu Chen
 
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001rainx1982
 
Uliweb设计分享
Uliweb设计分享Uliweb设计分享
Uliweb设计分享modou li
 
Single-Page Application Design Principles 101
Single-Page Application Design Principles 101Single-Page Application Design Principles 101
Single-Page Application Design Principles 101Jollen Chen
 
Ibm connections在工程建设中的应用
Ibm connections在工程建设中的应用Ibm connections在工程建设中的应用
Ibm connections在工程建设中的应用Flanker Dai
 
4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdfssuserd6c7621
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Wade Huang
 
Google+c++编程风格指南
Google+c++编程风格指南Google+c++编程风格指南
Google+c++编程风格指南also24
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source ProjectsGeorge Ang
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojectsGeorge Ang
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题yiditushe
 

Similar to 111 (20)

第1讲 开始编写程序
第1讲 开始编写程序第1讲 开始编写程序
第1讲 开始编写程序
 
Programming in Objective-C
Programming in Objective-CProgramming in Objective-C
Programming in Objective-C
 
N bear
N bearN bear
N bear
 
Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)
 
Xcode开发员入门导引
Xcode开发员入门导引Xcode开发员入门导引
Xcode开发员入门导引
 
Clipper@datacon.2019.tw
Clipper@datacon.2019.twClipper@datacon.2019.tw
Clipper@datacon.2019.tw
 
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001
 
Uliweb设计分享
Uliweb设计分享Uliweb设计分享
Uliweb设计分享
 
Single-Page Application Design Principles 101
Single-Page Application Design Principles 101Single-Page Application Design Principles 101
Single-Page Application Design Principles 101
 
Ibm connections在工程建设中的应用
Ibm connections在工程建设中的应用Ibm connections在工程建设中的应用
Ibm connections在工程建设中的应用
 
4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有
 
Google+c++编程风格指南
Google+c++编程风格指南Google+c++编程风格指南
Google+c++编程风格指南
 
Les 3 ppt
Les 3 pptLes 3 ppt
Les 3 ppt
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
SCJP ch09
SCJP ch09SCJP ch09
SCJP ch09
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source Projects
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojects
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题
 

More from GARNETT2183 (8)

Report_iDisk_1
Report_iDisk_1Report_iDisk_1
Report_iDisk_1
 
NDA
NDANDA
NDA
 
Test 2
Test 2Test 2
Test 2
 
test
testtest
test
 
Test
TestTest
Test
 
111
111111
111
 
111
111111
111
 
12453
1245312453
12453
 

111

  • 1. 从 C&C++过渡到 Objective-C 序: 对于已经熟悉 C++的人来说,从事 iPhone 开发一开始就陷入过多的 Objective-C 的细节可 能并非好事。 我们希望可以更加关注于 iPhone 开发特有的东西,快速上手。 下面这些内容可以帮助 C++程序员快速获得 Objective-C 的基本知识,并开始编写和阅读 iPhone 程序,如果在读别人的程序时,有些语法搞不懂,可以翻查我前面发的那本电子书 《 <Cocoa 入 门 --- 使 用 Objective-C> 英 文 版 》 (http://www.weiphone.com/thread-119791-1-1.html),把其作为参考手册用。 以 下 内 容 均 整 理 / 翻 译 自 《 iPhone Open Application Development 》 (http://www.weiphone.com/thread-119662-1-1.html) 编/译者: yangqiang.alan@gmail.com 1、消息 你应该注意的第一件事情就是 Objective-C 中大量使用了中括号。在 Objective-C 中,方法 不是使用传统形式(C/C++的语法形式)“调用”的;代替的是,“方法调用”变成了“消息 发送”。与此类似,“方法返回”,变成了“消息响应”。在 C 中,在调用方法之前必须预先 将其定义好;而 Objective-C 的消息风格,允许开发者在运行时动态创建方法和消息。这样
  • 2. 做的负面影响就是:完全允许向一个对象发送一个不可能返回的消息,这将导致异常,进而 可能让程序崩溃。 这里有一个对象 myWidget,一个消息可以被发送到它的 powerOn 方法上,像这样: returnValue = [ myWidget powerOn ]; 如果用 C++做同样的事情,则像这样: returnValue = myWidget->powerOn(); C 则会在其扁平的名字空间上声明一个函数: returnValue = widget_powerOn(myWidget); 只要一个对象可以接收,就可以向其传递参数。下面的例子调用了一个 setSpeed 方法,并 传递了两个参数: returnValue = [ myWidget setSpeed: 10.0 withMass: 33.0 ]; 注意,在这个消息中,第二个参数使用了显式名称(explicitly named)。这就允许声明多个具 有相同名称和类型的方法——即多态。 returnValue = [ myWidget setSpeed: 10.0 withMass: 33.0 ]; returnValue = [ myWidget setSpeed: 10.0 withGyroscope: 10.0 ]; 2、类与方法声明 尽管可以在 Objective-C 中定义 C++的类,但最好能善用 Objective-C 自己的对象和特性。 Objective-C 中有接口的概念。在标准 C++中,类是结构,而类的变量和方法是被包含在结 构中的。Objective-C 中,把类的变量放在 one part of the class 中,方法放在另一部分中。 Objective-C 要求把 interface 声明在其自己的代码块中(in its own code block),称为 @interface;而其实现则定义在@implementation 代码块中。方法自身的构造跟 Smalltalk
  • 3. 很像,看其来跟 C 非常不同。 我们的组件(widget)的 interface 是下面这样的,放在一个 MyWidget.h 文件中。 #import <Foundation/Foundation.h> @interface MyWidget : BaseWidget { BOOL isPoweredOn; @private float speed; @protected float mass; @protected float gyroscope; } + (id)alloc; + (BOOL)needsBatteries; - (BOOL)powerOn; - (void)setSpeed:(float)_speed; - (void)setSpeed:(float)_speed withMass:(float)_mass; - (void)setSpeed:(float)_speed withGyroscope:(float)_gyroscope; @end 在下面的小节中会详细解释这个文件中的重要语义元素。 2.1、Import 使用预处理指令#import 代替传统的#include 指令(尽管#include 还是可以使用的)。使用
  • 4. #import 的一个好处就是:它内建的逻辑可以保证相同的资源不会被包含多于一次。这就可 以避免像在 C 代码中那样,使用这样的宏: #ifndef _MYWIDGET_H #define _MYWIDGET_H ... #endif 2.2、interface 声明 使用@interface 语句再跟上接口名和基类(如果有基类的话),来声明一个接口。此代码块使 用@end 语句结束。 2.3、方法 方法声明放在花括号结构的外面。+号表示这是一个静态方法,而-号声明这个方法是一个实 例方法。可以使用 MyWidget 类的引用直接调用 alloc 方法(分配一个新对象),而 MyWidget 类的实例方法(比如 needsBatteries 和 powerOn),就通过 alloc 返回的类实例来调用。 方法声明的每个参数,都使用数据类型、局部变量名和一个可选的外部变量名(external variable name)来表示。外部变量名的例子就是上面程序中的 withMass 和 withGyroscope。 方法调用者在调用方法时,使用外部变量名;但在方法内部,则使用局部变量名来引用这个 参数。这样,setSpeed 方法就使用局部变量_mass 来获取传递进来的 withMass 的值。 如果在声明中没有提供外部变量名,则调用者只会使用一个冒号来引用这个变量,比 如 :10.0。
  • 5. 3、实现 Objective-C 源文件的后缀是.m。前面小节中 widget 类的骨架实现(skeletion implementation) 如下,放在一个 MyWidget.m 文件中。 #import "MyWidget.h" @implementation MyWidget + (id)alloc { } + (BOOL)needsBatteries { return YES; } - (BOOL)powerOn { isPoweredOn = YES; return YES; } - (void)setSpeed:(float)_speed { speed = _speed; }
  • 6. - (void)setSpeed:(float)_speed withMass:(float)_mass { speed = _speed; mass = _mass; } - (void)setSpeed:(float)_speed withGyroscope:(float)_gyroscope { speed = _speed; gyroscope = _gyroscope; } @end 就好像接口放在它自己的代码块中一样,实现放在由@implementation 语句开始、@end 语句结束的代码块中。在 C++中,使用 m_作为成员变量名的前缀,是一同常见的做法。而 Objective-C 中,局部变量名使用下划线作为前缀,通过外部变量名,向别人提供可读的变 量名称。 4、Category Objective-C 向面向对象编程中增加了一个新的元素:称为 category。Category 被设计用来 解决这样的问题:基类被认为是脆弱的,应该避免对其进行看起来无害的改变,因为这样可 能会破坏更加复杂的派生类。当一个程序增长到特定的规模时,开发者经常害怕去触摸那个 较小的基类,因为如果不对整个应用程序详细审查,就无法确定:对基类的改变是否安全。
  • 7. Category 提供了一个机制,来为基类增加功能,而不影响其他的对象。 category 类可以增加和替换一些基类的方法。这可以在不重新编译基类、甚至不必访问基 类源代码的情况下做到。Category 允许在有限的范围内(within a limited scope)对基类进行 扩展(expanded),那么任何使用基类(而非 category 类)的对象,将继续看到原始的版本。 从开发的角度看,这使得你更容易改进其他开发者所写的类。在运行时,使用 category 的 代码部分将看到这个类的新版本,而直接使用基类的代码则只看到原始版本。 组件工厂发布了一种新型的组件,它可以在太空中飞行,但是如果改变它们的基类,将可能 破坏已经存在的应用。通过构建一个 category,使用 MyWidget 基类的应用程序将继续看见 这个原始类;而新的太空应用将使用 category。下面的例子在已经存在的 MyWidget 基类上 构建了一个新的 category,名为 MySpaceWidget。因为我们需要在太空中爆炸的能力,所 以增加了一个名为 selfDestruct 的方法。这个 category 还用自己的方法替换了已经存在的 powerOn 方法。对比一下:这里使用了圆括号包含 MySpaceWidget,来定义 category;而 在上面的例子中使用的是冒号来定义继承。 #import "MyWidget.h" @interface MyWidget (MySpaceWidget) - (void)selfDestruct; - (BOOL)powerOn; @end 下面是该 category 的实现: #import "MySpaceWidget.h"
  • 8. @implementation MyWidget (MySpaceWidget) - (void)selfDestruct { isPoweredOn = 0; speed = 1000.0; mass = 0; } - (BOOL)powerOn { if (speed == 0) { isPoweredOn = YES; return YES; } /* Don't power on if the spaceship is moving */ return NO; } @end 5、Pose(伪装) 在 Objective-C 中,子类对象可以伪装成其父类(pose as one of its superclasses),替换父 类对象接收所有的消息。这跟 overriding(重写)很像,但 overriding 只能重写整个类,而非
  • 9. 单个方法。在 Pose 类中,不能声明任何新成员变量,但可以重写或替换已经存在的方法。 Pose 跟 Category 有点相似,它们都允许开发者在运行时扩展一个已经存在的类(augment an existing class at runtime)。 在前面的例子里,创建了一些机械组件类(mechanical widget classes)。随后,在定义了所 有这些组件之后,发现了永久能源。这就允许很多新的组件成为自治的了,然而老的组件仍 然需要电池。因为自治组件拥有非常庞大的不同代码,所以派生了一个名为 MyAutonomousWidget 的类,来重写所有需要改变的功能(比如静态的 needsBatteries 方 法)。 #import <Foundation/Foundation.h> #import "MyWidget.h" @interface MyAutonomousWidget : MyWidget { } + (BOOL)needsBatteries; @end #import "MyAutonomousWidget.h" @implementation MyAutonomousWidget + (BOOL)needsBatteries { return NO; }
  • 10. @end 自治类不是改变所有已经存在的代码,而是可以简单的伪装成一个组件类。在主程序或其他 高阶(high-level)方法中调用 class_poseAs 方法,从而达到此目的: MyAutonomousWidget *myAutoWidget = [ MyAutonomousWidget alloc ]; MyWidget *myWidget = [ MyWidget alloc ]; class_poseAs(myAutoWidget, myWidget); 从这里开始,我们放在 pose 类中的任何其他方法(给自治设备用的)都将伪装成原来的基类 被使用。