java中dynamic_介绍@dynamic的用法

介绍@dynamic的用法

Objective-C 2.0提供了属性(@property),可以让编译器自动生成setter和getter方法。如果不想编译器自作主张生成这些setter和getter方法,则使用@dynamic。举个简单例子,如下#import

@interface Person : NSObject

@property (copy) NSString *name;

@end

@implementation Person

// @dynamic tells compiler don't generate setter and getter automatically

@dynamic name;

@end

int main(int argc, const charchar * argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Person *a = [[Person alloc] init];

a.name = @"Hello"; // will crash here

NSLog(@"%@", a.name);

[a release];

[pool drain];

return 0;

} // main

运行该程序,Xcode会报错“-[PersonsetName:]: unrecognized selector sent to instance 0x1001149d0”。如果将@dynamic注释掉,则一切Ok。

这里由于使用@dynamic,我们需要自己提供setter和getter方法。一般有两种方法:1)自己提供setter和getter方法,将编译器自动生成的setter和getter方法手动再写一遍;2)动态方法决议(DynamicMethod Resolution),在运行时提供setter和getter对应实现的C函数。

对于第一种方法,需要在类中显式提供实例变量,因为@dynamic不能像@synthesize那样向实现文件(.m)提供实例变量。#import

@interface Person : NSObject

{

// must provide a ivar for our setter and getter

NSString *_name;

}

@property (copy) NSString *name;

@end

@implementation Person

// @dynamic tells compiler don't generate setter and getter automatically

@dynamic name;

// We provide setter and getter here

- (void) setName:(NSString *)name

{

if (_name != name) {

[_name release];

_name = [name copy];

}

}

- (NSString *) name

{

return _name;

}

@end // Person

int main(int argc, const charchar * argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Person *a = [[Person alloc] init];

a.name = @"Hello"; // Ok, use our setter

a.name = @"Hello, world";

NSLog(@"%@", a.name); // Ok, use our getter

[a release];

[pool drain];

return 0;

} // main

对于第二种方法,在运行时决定setter和getter对应实现的C函数,使用了NSObject提供的resolveInstanceMethod:方法。在C函数中不能直接使用实例变量,需要将ObjC对象self转成C中的结构体,因此在Person类同样需要显式声明实例变量而且访问级别是@public,为了隐藏该实例变量,将声明放在扩展(extension)中#import

#import // for class_addMethod()

// ------------------------------------------------------

// A .h file

@interface Person : NSObject

@property (copy) NSString *name;

- (void) hello;

@end

// ------------------------------------------------------

// A .m file

// Use extension to override the access level of _name ivar

@interface Person ()

{

@public

NSString *_name;

}

@end

@implementation Person

// @dynamic implies compiler to look for setName: and name method in runtime

@dynamic name;

// Only resolve unrecognized methods, and only load methods dynamically once

+ (BOOL) resolveInstanceMethod:(SEL)sel

{

// Capture setName: and name method

if (sel == @selector(setName:)) {

class_addMethod([self class], sel, (IMP)setName, "v@:@");

return YES;

}

else if (sel == @selector(name)) {

class_addMethod([self class], sel, (IMP)getName, "@@:");

return YES;

}

return [super resolveInstanceMethod:sel];

}

void setName(id self, SEL _cmd, NSString* name)

{

// Implement @property (copy)

if (((Person *)self)->_name != name) {

[((Person *)self)->_name release];

((Person *)self)->_name = [name copy];

}

}

NSString* getName(id self, SEL _cmd)

{

return ((Person *)self)->_name;

}

- (void) hello

{

NSLog(@"Hello, world");

}

@end // Person

int main(int argc, const charchar * argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Person *a = [[Person alloc] init];

[a hello]; // never call resolveInstanceMethod

a.name = @"hello1";

NSLog(@"%@", a.name);

a.name = @"hello2";

NSLog(@"%@", a.name);

[a release];

[pool drain];

return 0;

} // main

总结以上,@dynamic的作用就是禁止编译器为@property产生setter和getter方法,有两种办法实现setter和getter方法:1)自己提供setter和getter方法;2)方法动态决议(DynamicMethod Resolution)。

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值