objective-C中的扩展方法与partial class

在c#中要扩展一个现有类非常easy,比方这样:

?

1

2

3

4

5

6

7

publicstaticclassUtils

{

publicstaticvoidPrintToConsole(thisstringstrSrc)

{

Console.WriteLine(strSrc);

}

}

这样就为String类加入了一个PrintToConsole的方法。用法例如以下:

?

1

2

3

4

5

6

7

classMainClass

{

publicstaticvoidMain (string[] args)

{

"Hello World!".PrintToConsole();

}

}

在objective-C中,也有类似的处理办法:

StringUtils.h 定义部分

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. @interface NSString(ExtNSString)
  3. -(void) PrintToConSole;
  4. @end

解释:@interface NSString(ExtNSString) 表示ExtNSString这个类将会扩展NSString,会为其添加一些通用的额外方法。

StringUtils.m 实现部分

[objc]view plaincopy

  1. #import "StringUtils.h"
  2. @implementation NSString(ExtNSString)
  3. -(void) PrintToConSole
  4. {
  5. NSLog(@"%@",self);
  6. }
  7. @end

用法例如以下:

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "StringUtils.h"
  3. int main (int argc, const charchar * argv[]) {
  4. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  5. NSString* str = @"Hello World!";
  6. [str PrintToConSole];
  7. [pool drain];
  8. return 0;
  9. }

只是有一点要特别注意:c#中假设开发者添加的扩展方法跟.net框架自带的现有方法重名,实际执行时将以系统自带的现有方法为准。但在obj-C中,这样的情况下开发者新添加的重名方法会覆盖系统原有的方法,并且没有不论什么提示!

一个好的习惯是为全部扩展方法(包含类名),都加一个特殊的前缀或后缀。以避免重名。

下一个话题:partial class

做过asp.net开发的程序猿都知道,c#中的partial class能够方便的将同一个类的代码,分散在多个不同的物理文件里,编译器在编译时能自己主动将它们合并。这是一个非常棒的功能。在团队开发中我常常把一个类的不同业务模块,分散成几个不同的物理文件(比方class_jimmy.cs。class_mike.cs...),然后jimmy仅仅在class_jimmy.cs中写代码。mike仅仅在class_mike.cs中写代码,在非常大程度上这样能够降低(或避免)终于svn提交合并时的冲突。

表面上看,partial class与扩展方法是风马牛不相及的二个概念。可是在obj-C中,这二个事实上是一回事。

场景:比方一个商城系统,对产品的增、删、改定义。我想单独放到文件Product.h中,而对订单的处理,我想单独放到文件Order.h中。可是这些跟业务相关的处理,我想在逻辑上把它们都归到同一个类BLL.h中。

看看obj-C中的做法:(主要是看几个文件是怎样组织成一个类的。代码仅仅是演示样例而已)

1、先定义BLL.h (主要用于放一些成员变量。基本上仅仅是一个壳而已)

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. @interface BLL : NSObject {
  3. NSString* connStr;
  4. }
  5. -(void) setConnString:(NSString*) connString;
  6. -(NSString*) connString;
  7. @end

BLL.m实现

[objc]view plaincopy

  1. #import "BLL.h"
  2. @implementation BLL
  3. -(void) setConnString:(NSString *)connString
  4. {
  5. connStr = connString;
  6. }
  7. -(NSString*) connString
  8. {
  9. return connStr;
  10. }
  11. -(void) dealloc
  12. {
  13. [connStr release];
  14. [super dealloc];
  15. }
  16. @end

2、再定义Product.h用来扩展BLL类

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "BLL.h"
  3. @interface BLL(Product)
  4. -(void) addProduct: (NSString* )productName productNo:(NSString*)proNo;
  5. -(void) deleteProduct:(NSString*) productNo;
  6. @end

Product.m

[objc]view plaincopy

  1. #import "Product.h"
  2. #import "BLL.h"
  3. @implementation BLL(Product)
  4. -(void) addProduct: (NSString* )productName productNo:(NSString*)proNo
  5. {
  6. NSLog(@"connString=%@",connStr);//输出Bll.h中定义的成员connStr
  7. NSLog(@"addProduct success! productName:%@,productNo:%@",productName,proNo);
  8. }
  9. -(void) deleteProduct:(NSString*) productNo
  10. {
  11. NSLog(@"connString=%@",[self connString]);//也能够用属性来訪问
  12. NSLog(@"deleteProduct success! productNo:%@",productNo);
  13. }
  14. @end

3、定义Order.h继续扩展BLL类

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "BLL.h"
  3. @interface BLL(Order)
  4. -(void) createOrder:(NSString*) productNo quantity:(int) amount;
  5. @end

Order.m

[objc]view plaincopy

  1. #import "Order.h"
  2. @implementation BLL(Order)
  3. -(void) createOrder:(NSString*) productNo quantity:(int) amount
  4. {
  5. NSLog(@"thank you for order our product. productNo:%@,quantity:%d",productNo,amount);
  6. }
  7. @end

因为Product类与Order类都是扩展自BLL类。所以这三个类在逻辑上都是同一个类BLL,最后来看看怎样使用:

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "BLL.h"
  3. #import "Product.h"
  4. #import "Order.h"
  5. int main (int argc, const charchar * argv[]) {
  6. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  7. BLL *bll = [[BLL alloc] init];
  8. bll.connString = @"I am connection string.";
  9. [bll addProduct:@"iphone4" productNo:@"0001"];//调用Product.h中定义的方法
  10. [bll createOrder:@"0001" quantity:5]; //调用Order.h中定义的方法
  11. [bll deleteProduct:@"0001"];
  12. [bll release];
  13. [pool drain];
  14. return 0;
  15. }

执行结果:

2011-02-26 22:29:30.369 Demo[1292:a0f] connString=I am connection string.

2011-02-26 22:29:30.376 Demo[1292:a0f] addProduct success! productName:iphone4,productNo:0001

2011-02-26 22:29:30.378 Demo[1292:a0f] thank you for order our product. productNo:0001,quantity:5

2011-02-26 22:29:30.379 Demo[1292:a0f] connString=I am connection string.

2011-02-26 22:29:30.380 Demo[1292:a0f] deleteProduct success! productNo:0001

皆大欢喜。非常多语言和技术真是“一门通。处处通”,或许:c#中的"扩展方法"与"部分类"的设计灵感正是来自objective-C。

在c#中要扩展一个现有类非常easy,比方这样:

?

1

2

3

4

5

6

7

publicstaticclassUtils

{

publicstaticvoidPrintToConsole(thisstringstrSrc)

{

Console.WriteLine(strSrc);

}

}

这样就为String类加入了一个PrintToConsole的方法。用法例如以下:

?

1

2

3

4

5

6

7

classMainClass

{

publicstaticvoidMain (string[] args)

{

"Hello World!".PrintToConsole();

}

}

在objective-C中,也有类似的处理办法:

StringUtils.h 定义部分

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. @interface NSString(ExtNSString)
  3. -(void) PrintToConSole;
  4. @end

解释:@interface NSString(ExtNSString) 表示ExtNSString这个类将会扩展NSString,会为其添加一些通用的额外方法。

StringUtils.m 实现部分

[objc]view plaincopy

  1. #import "StringUtils.h"
  2. @implementation NSString(ExtNSString)
  3. -(void) PrintToConSole
  4. {
  5. NSLog(@"%@",self);
  6. }
  7. @end

用法例如以下:

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "StringUtils.h"
  3. int main (int argc, const charchar * argv[]) {
  4. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  5. NSString* str = @"Hello World!";
  6. [str PrintToConSole];
  7. [pool drain];
  8. return 0;
  9. }

只是有一点要特别注意:c#中假设开发者添加的扩展方法跟.net框架自带的现有方法重名,实际执行时将以系统自带的现有方法为准。但在obj-C中,这样的情况下开发者新添加的重名方法会覆盖系统原有的方法,并且没有不论什么提示!

一个好的习惯是为全部扩展方法(包含类名),都加一个特殊的前缀或后缀。以避免重名。

下一个话题:partial class

做过asp.net开发的程序猿都知道,c#中的partial class能够方便的将同一个类的代码,分散在多个不同的物理文件里,编译器在编译时能自己主动将它们合并。这是一个非常棒的功能。在团队开发中我常常把一个类的不同业务模块,分散成几个不同的物理文件(比方class_jimmy.cs。class_mike.cs...),然后jimmy仅仅在class_jimmy.cs中写代码。mike仅仅在class_mike.cs中写代码,在非常大程度上这样能够降低(或避免)终于svn提交合并时的冲突。

表面上看,partial class与扩展方法是风马牛不相及的二个概念。可是在obj-C中,这二个事实上是一回事。

场景:比方一个商城系统,对产品的增、删、改定义。我想单独放到文件Product.h中,而对订单的处理,我想单独放到文件Order.h中。可是这些跟业务相关的处理,我想在逻辑上把它们都归到同一个类BLL.h中。

看看obj-C中的做法:(主要是看几个文件是怎样组织成一个类的。代码仅仅是演示样例而已)

1、先定义BLL.h (主要用于放一些成员变量。基本上仅仅是一个壳而已)

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. @interface BLL : NSObject {
  3. NSString* connStr;
  4. }
  5. -(void) setConnString:(NSString*) connString;
  6. -(NSString*) connString;
  7. @end

BLL.m实现

[objc]view plaincopy

  1. #import "BLL.h"
  2. @implementation BLL
  3. -(void) setConnString:(NSString *)connString
  4. {
  5. connStr = connString;
  6. }
  7. -(NSString*) connString
  8. {
  9. return connStr;
  10. }
  11. -(void) dealloc
  12. {
  13. [connStr release];
  14. [super dealloc];
  15. }
  16. @end

2、再定义Product.h用来扩展BLL类

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "BLL.h"
  3. @interface BLL(Product)
  4. -(void) addProduct: (NSString* )productName productNo:(NSString*)proNo;
  5. -(void) deleteProduct:(NSString*) productNo;
  6. @end

Product.m

[objc]view plaincopy

  1. #import "Product.h"
  2. #import "BLL.h"
  3. @implementation BLL(Product)
  4. -(void) addProduct: (NSString* )productName productNo:(NSString*)proNo
  5. {
  6. NSLog(@"connString=%@",connStr);//输出Bll.h中定义的成员connStr
  7. NSLog(@"addProduct success! productName:%@,productNo:%@",productName,proNo);
  8. }
  9. -(void) deleteProduct:(NSString*) productNo
  10. {
  11. NSLog(@"connString=%@",[self connString]);//也能够用属性来訪问
  12. NSLog(@"deleteProduct success! productNo:%@",productNo);
  13. }
  14. @end

3、定义Order.h继续扩展BLL类

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "BLL.h"
  3. @interface BLL(Order)
  4. -(void) createOrder:(NSString*) productNo quantity:(int) amount;
  5. @end

Order.m

[objc]view plaincopy

  1. #import "Order.h"
  2. @implementation BLL(Order)
  3. -(void) createOrder:(NSString*) productNo quantity:(int) amount
  4. {
  5. NSLog(@"thank you for order our product. productNo:%@,quantity:%d",productNo,amount);
  6. }
  7. @end

因为Product类与Order类都是扩展自BLL类。所以这三个类在逻辑上都是同一个类BLL,最后来看看怎样使用:

[objc]view plaincopy

  1. #import <Foundation/Foundation.h>
  2. #import "BLL.h"
  3. #import "Product.h"
  4. #import "Order.h"
  5. int main (int argc, const charchar * argv[]) {
  6. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  7. BLL *bll = [[BLL alloc] init];
  8. bll.connString = @"I am connection string.";
  9. [bll addProduct:@"iphone4" productNo:@"0001"];//调用Product.h中定义的方法
  10. [bll createOrder:@"0001" quantity:5]; //调用Order.h中定义的方法
  11. [bll deleteProduct:@"0001"];
  12. [bll release];
  13. [pool drain];
  14. return 0;
  15. }

执行结果:

2011-02-26 22:29:30.369 Demo[1292:a0f] connString=I am connection string.

2011-02-26 22:29:30.376 Demo[1292:a0f] addProduct success! productName:iphone4,productNo:0001

2011-02-26 22:29:30.378 Demo[1292:a0f] thank you for order our product. productNo:0001,quantity:5

2011-02-26 22:29:30.379 Demo[1292:a0f] connString=I am connection string.

2011-02-26 22:29:30.380 Demo[1292:a0f] deleteProduct success! productNo:0001

皆大欢喜。非常多语言和技术真是“一门通。处处通”,或许:c#中的"扩展方法"与"部分类"的设计灵感正是来自objective-C。