object-c的Categories

本文通过两个示例介绍了如何在Objective-C中使用Categories为已有类添加新方法,并实现类似C++或Java中对类方法的访问控制(如private、protected、public)。通过修改类的实现细节,可以在不改变原有类结构的情况下扩展其功能,并控制方法的可见性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Categories允许用户为某个类添加新的方法(不能添加新的数据成员),而不用继承的方式来实现。并且,即使没有某个类的实现源码,仍然可以这样做。实例如下:
一.  例1:在不用Fraction源码的情况下,为Fraction添加几个数学(math)方法。 
1. 代码: 
    需要把之前编译好的Fraction.o和Fraction.h放到和下面文件的同一个目录下,例如,这里是FractionMath目录。 
   //1. FractionMath.h
#import "Fraction.h"


@interface Fraction (Math)
-(Fraction*) add: (Fraction*) f;
-(Fraction*) mul: (Fraction*) f;
-(Fraction*) div: (Fraction*) f;
-(Fraction*) sub: (Fraction*) f;
@end
    //2. FractionMath.m
#import "FractionMath.h"


@implementation Fraction (Math)
-(Fraction*) add: (Fraction*) f {
    return [[Fraction alloc] initWithNumerator: numerator * [f denominator] +
                                                denominator * [f numerator]
                             denominator: denominator * [f denominator]];
}


-(Fraction*) mul: (Fraction*) f {
    return [[Fraction alloc] initWithNumerator: numerator * [f numerator]
                             denominator: denominator * [f denominator]];


}


-(Fraction*) div: (Fraction*) f {
    return [[Fraction alloc] initWithNumerator: numerator * [f denominator]
                             denominator: denominator * [f numerator]];
}


-(Fraction*) sub: (Fraction*) f {
    return [[Fraction alloc] initWithNumerator: numerator * [f denominator] -
                                                denominator * [f numerator]
                             denominator: denominator * [f denominator]];
}
@end


//3. main.m
#import <stdio.h>
#import "Fraction.h"
#import "FractionMath.h"


int main( int argc, const char *argv[] ) {
    // create a new instance
    Fraction *frac1 = [[Fraction alloc] initWithNumerator: 1 denominator: 3];
    Fraction *frac2 = [[Fraction alloc] initWithNumerator: 2 denominator: 5];
    Fraction *frac3 = [frac1 mul: frac2];


    // print it
    [frac1 print];
    printf( " * " );
    [frac2 print];
    printf( " = " );
    [frac3 print];
    printf( "\n" );


    // free memory
    [frac1 release];
    [frac2 release];
    [frac3 release];


    return 0;
}


2. 编译运行
gcc -fconstant-string-class=NSConstantString -c main.m -I /GNUstep/System/Library/Headers
gcc -c FractionMath.m -I /GNUstep/System/Library/Headers
gcc main.o Fraction.o FractionMath.o -o main -L /GNUstep/System/Library/Libraries/ -lobjc -lgnustep-base


$ ./main.exe
1/3 * 2/5 = 2/15


3.说明:
  (1) 必须将 Fraction.o和Fraction.h放在代码的同一个目录下,这才能引用到,否则,在链接的时候就找不到Fraction类。 


二. 例2:      在C++(或Java)那样,对类的方法可以用private/protected/public来限制类方法的访问防属性;然而,在object-c中,却没有这样的规定(有的只是对成员变量的限制),  现在,可以用 categories 来实现这样的功能。实例如下:


    1. 代码:
    //1.  ClassA.h
#import <Foundation/NSObject.h>


@interface ClassA: NSObject 


-(void) print;
@end 


//2. ClassA.m
#import "ClassA.h"


@implementation ClassA


//在.h中有声明,这是个public方法
-(void) print {
    printf( "this is a public method\n");
}
@end


// private 方法
@interface MyClass (Private)
-(void) privateMethod;
@end


@implementation MyClass (Private)
-(void) privateMethod {
    printf( "this is a private method\n" );
}
@end




//3. main.m
#import <stdio.h>
#import "ClassA.h"


int main( int argc, const char *argv[] ) {
    // create a new instance
    ClassA *a = [[ClassA alloc] init];


    [a print];
    printf( "\n" );
    
    //下面这个函数会编译出错,因为这个函数是在.m中声明的,不能被外部访问,这就间接实现了private功能。
    //[a privateMethod];
    return 0;
}


二. 编译运行(略) 
三. 说明:

    (1) 在.h中声明的print函数可以认为是public的; 
    (2) 在.m中用 "@interface MyClass (Private)"方式声明的,不能被外部访问,所以,间接的实现了private功能。
    (3) 当然,可以把"private"改为其它的单词,例如"aaaaaaa",都是可以的;

    (4) 对比例一,关键的区别是这个声明是在.h中声明的,还是在.m中声明的,如果是前者,那么,在外部就可以访问,本来的目就是为类扩展函数,正如例1一样;  如果在.m中声明,那么,外部就访问不到了。

    (5) 从另一个角度理解,在访问一个类的时候,需要import .h头文件的,如果在.h文件中没有相应函数的声明,那么,就会出现编译错误了,这也很容易理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值