在c#中要扩展一个现有类非常easy,比方这样:
?
1
2
3
4
5
6
7
public static class Utils
{
    public static void PrintToConsole(this string strSrc)
    {
        Console.WriteLine(strSrc);
    }  
}
这样就为String类加入了一个PrintToConsole的方法。用法例如以下:
?
1
2
3
4
5
6
7
class MainClass
{
    public static void Main
(
string[]
args)
    {
        "Hello
World!"
.PrintToConsole();           
    }
}
在objective-C中,也有类似的处理办法:
StringUtils.h 定义部分
  1. #import <Foundation/Foundation.h>
  2. @interface NSString(ExtNSString)
  3. -(void) PrintToConSole;
  4. @end
解释:@interface NSString(ExtNSString) 表示ExtNSString这个类将会扩展NSString,会为其添加一些通用的额外方法。
 
StringUtils.m 实现部分
  1. #import "StringUtils.h"
  2. @implementation NSString(ExtNSString)
  3. -(void) PrintToConSole
  4. {
  5. NSLog(@"%@",self);
  6. }
  7. @end
用法例如以下:
  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 (主要用于放一些成员变量。基本上仅仅是一个壳而已)
  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实现
  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类
  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
  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类

  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

  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,最后来看看怎样使用:

  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。

objective-C中的扩展方法与partial class的更多相关文章

  1. C#3.0中的扩展方法

    在实际应用中,开发者完成代码的编译后,除非重新编译更改后的代码,否则开发者很难在原有代码中添加新的功能. 在C#3.0中,提供了一个扩展方法的新特性,可以使得开发者在编译后的程序集里边添加相关的方法, ...

  2. 记录C#中的扩展方法

    C#中的扩展方法. 系统自带的类型,我们无法去修改: 修改源代码需要较大的精力,而且可能会带来错误: 我们只是需要一个或者较少的几个方法,修改源代码费时费力: 被扩展的类是sealed的,不能被继承: ...

  3. C#编程(六十一)------------LINQ中的扩展方法

    原文链接: http://blog.csdn.net/shanyongxu/article/details/47208401 LINQ中的扩展方法 LINQ中where扩展方法,要想使用,必须导入us ...

  4. C#中的扩展方法(向已有类添加方法,但无需创建新的派生类型)

    C#中的扩展方法 扩展方法使你能够向现有类型"添加"方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样 ...

  5. C#中的扩展方法详解

    “扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.”这是msdn上说的,也就是你可以对String,Int,DataRow,DataTable等这些类 ...

  6. C#中的扩展方法

    扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 以上是msdn官网对扩展方 ...

  7. Enum扩展及MVC中DropDownListFor扩展方法的使用

    public enum SearchState { /// <summary> /// 全部 /// </summary> [Description("全部" ...

  8. 19.C#逐一介绍IEnumerable和IEnumerable<T>中的扩展方法(10.3-10.5)

    今天没有太多的言语,只有代码,扩展方法多得太多,不能一一列完,书中一些,看多了也就会使用了. //Enumerable.Range 返回起始到结束范围,是一个Enumrable<int>类 ...

  9. MVC 中使用扩展方法

     扩展方法(Extension Method)是给那些不是你拥有.因而不能直接修改的类添加方法的一种方便的办法. 一.使用扩展方法 1.定义一个购物车的类-ShoppingCart using Sys ...

随机推荐

  1. Jmeter插件之PerfMon监控插件使用说明

    PerfMon是Jmeter用来监控系统资源的一款插件,可以用来监控系统的cpu.内存.I/O等性能指标. 首先是Jmeter的插件安装,需要先下载JMeter Plugins Manager这个插件 ...

  2. String format -1 常规格式化

    常规类型的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的读者应该记得C语言的sprintf()方法,两者有类似之处.format()方法有两种重 ...

  3. view update

    CREATE OR REPLACE VIEW [Current Product List] ASSELECT ProductID, ProductName, CategoryFROM Products ...

  4. Redis主从复制、哨兵模式

    1.部署主从 环境:主IP:10.0.0.15,端口6379;从IP:10.0.0.16,端口6379. 原理:基于RDB持久化的功能来实现主从复制的功能. a.linux-redis1(10.0.0 ...

  5. 深入JS正则先行断言

    这里是 Mastering Lookahead and Lookbehind 文章的简单翻译,这篇文章是在自己搜索问题的时候stackoverflow上回答问题的人推荐的,看完觉得写得很不错.这里的简 ...

  6. 一个错误使用单例模式的场景及ThreadLocal简析

    近来参与一个Java的web办公系统,碰到一个bug,开始猜测是线程池管理的问题,最后发现是单例模式的问题. 即,当同时发起两个事务请求时,当一个事务完成后,另一个事务会抛出session is cl ...

  7. Broken Code

    给一个sorted array 0 0 0 1 1 1 1,然后找出第一个1的位置. 边界情况:array为空或者全0. 思路:二分查找.为了优化,可以先判断最后一个数是不是0. class Solu ...

  8. 六. 异常处理5.多重catch语句的使用

    某些情况,由单个代码段可能引起多个异常.处理这种情况,你可以定义两个或更多的catch子句,每个子句捕获一种类型的异常.当异常被引发时,每一个catch子句被依次检查,第一个匹配异常类型的子句执行.当 ...

  9. 关于MapControl和PageLayout地图同步的问题

    按照ArcMap的处理方式,地图和制图是分两个页面的,他们之间通过共享同一个Map对象来实现地图同步,具体做法就是在PageLayoutControl的PageLayoutReplaced事件发生时, ...

  10. 分布式协调服务Zookeeper

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...