专栏首页菩提树下的杨过objective-C中的扩展方法与partial class

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

 在c#中要扩展一个现有类很容易,比如这样:

	public static class Utils
	{
		public static void PrintToConsole(this string strSrc)
		{
			Console.WriteLine(strSrc);
		}	
	}

这样就为String类添加了一个PrintToConsole的方法,使用方法如下:

	class MainClass
	{
		public static void Main (string[] args)
		{
			"Hello World!".PrintToConsole();			
		}
	}

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

StringUtils.h 定义部分

#import <Foundation/Foundation.h>

@interface NSString(ExtNSString) 

-(void) PrintToConSole;

@end

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

StringUtils.m 实现部分

#import "StringUtils.h"

@implementation NSString(ExtNSString) 

-(void) PrintToConSole
{
	NSLog(@"%@",self);
}

@end

使用方法如下:

#import <Foundation/Foundation.h>
#import "StringUtils.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSString* str = @"Hello World!";
	
	[str PrintToConSole];
	
    [pool drain];
    return 0;
}

不过有一点要特别注意: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 (主要用于放一些成员变量,基本上只是一个壳而已)

#import <Foundation/Foundation.h>

@interface BLL : NSObject {	
	NSString* connStr;
}

-(void) setConnString:(NSString*) connString;
-(NSString*) connString;

@end

BLL.m实现

#import "BLL.h"

@implementation BLL

-(void) setConnString:(NSString *)connString
{
	connStr = connString;
}

-(NSString*) connString
{
	return connStr;
}

-(void) dealloc
{
	[connStr release];
	[super dealloc];
}
@end

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

#import <Foundation/Foundation.h>
#import "BLL.h"

@interface BLL(Product)

-(void) addProduct: (NSString* )productName productNo:(NSString*)proNo;
-(void) deleteProduct:(NSString*) productNo;

@end

Product.m

#import "Product.h"
#import "BLL.h"

@implementation BLL(Product)

-(void) addProduct: (NSString* )productName productNo:(NSString*)proNo
{
	NSLog(@"connString=%@",connStr);//输出Bll.h中定义的成员connStr
	NSLog(@"addProduct success! productName:%@,productNo:%@",productName,proNo);
}

-(void) deleteProduct:(NSString*) productNo
{
	NSLog(@"connString=%@",[self connString]);//也可以用属性来访问
	NSLog(@"deleteProduct success! productNo:%@",productNo);
}
@end

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

#import <Foundation/Foundation.h>
#import "BLL.h"

@interface BLL(Order)

-(void) createOrder:(NSString*) productNo quantity:(int) amount;

@end

Order.m

#import "Order.h"

@implementation BLL(Order)

-(void) createOrder:(NSString*) productNo quantity:(int) amount
{
	NSLog(@"thank you for order our product. productNo:%@,quantity:%d",productNo,amount);
}

@end

由于Product类与Order类都是扩展自BLL类,所以这三个类在逻辑上都是同一个类BLL,最后来看看如何使用:

#import <Foundation/Foundation.h>
#import "BLL.h"
#import "Product.h"
#import "Order.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	BLL *bll = [[BLL alloc] init];
	bll.connString = @"I am connection string.";
	[bll addProduct:@"iphone4" productNo:@"0001"];//调用Product.h中定义的方法
	[bll createOrder:@"0001" quantity:5];
	[bll deleteProduct:@"0001"];//调用Order.h中定义的方法
	[bll release];		
    [pool drain];
    return 0;
}

运行结果:

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。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Enterprise Library 4.1学习笔记5----实体验证程序块

    实体验证的作用简单来讲,就是从服务端对数据进行验证。(特别是对数据安全性要求比较高的应用,这是十分必要的) 废话不说了,直接讲下使用步骤:(因为我是做web开发...

    菩提树下的杨过
  • ExtJs学习笔记(16)_Form布局

    这是最重要的一个布局,几乎所有的表单界面都可以采用form布局,详细的用法本文不作讨论(可以查阅官方API文档),这里只给出一个简单的示例 <script ty...

    菩提树下的杨过
  • resteasy经验谈

    resteasy 是java体系中比较成熟的rest框架,也是jax-rs规范的实现之一,dubbox的REST服务框架,就是采用的resteasy实现,近日在...

    菩提树下的杨过
  • 每天一个linux命令:ls命令

    ls命令是linux下最常用的命令。ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清...

    用户7678152
  • 查看Hadoop HDFS 中的一个文件对应block信息

    本文地址:http://blog.csdn.net/chengyuqiang/article/details/78163091 如果需要查看Hadoop HDF...

    程裕强
  • Rabbitmq haproxy keepalived ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN.

    出现这种错误的情况有多种,比如guest用户访问时只允许localhost访问,或者用户名密码错误等。

    我是李超人
  • JQuery各种点击事件的区别

    在工作中,经常用到js的点击事件,有好多种表现形式,今天抽空总结一下它们的区别与联系。废话不多说,开始写测试案例。首先声明,本人水平有限,如果有错误之处,还请指...

    用户6182664
  • css3渐变:linear-gradient

    之前的实践中我们了解并熟悉了background-size,以及backgroud-clip,今天我们学习并实践的是线性渐变linear-gradient.

    RobinsonZhang
  • 腾讯离职创业4年 我的失败、迷茫与重生

    最近碰到经纬的张颖(注:经纬中国创始管理合伙人),张颖说“推事本”的创业故事挺励志的,可以写一写。此前我们一直埋头做自己的事情,没想过我们的经历是一个“励志”的...

    春哥大魔王
  • Android ViewDragHelper使用介绍

    ViewDragHelper是support.v4下提供的用于处理拖拽滑动的辅助类,查看Android的DrawerLayout源码,可以发现,它内部就是使用了...

    砸漏

扫码关注云+社区

领取腾讯云代金券