面试题答案
一键面试对成员变量的限制
- 无法直接声明实例变量:在Category中不能直接声明实例变量(Instance Variable)。例如,在一个类
Person
的Category中,如下代码会报错:
@interface Person (ExtraInfo) {
NSString * _nickname; // 报错,不能在Category中声明实例变量
}
@end
这是因为Category主要目的是为已有的类添加新的方法,而非扩展类的属性存储。
对方法声明的限制
- 无法覆盖原有方法:虽然可以在Category中声明与类中原有方法同名的方法,但并不会覆盖原有方法,而是会在运行时根据方法的调用顺序等规则来决定最终调用哪个方法。例如:
@interface Person : NSObject
- (void)sayHello;
@end
@implementation Person
- (void)sayHello {
NSLog(@"Original Hello");
}
@end
@interface Person (NewBehavior)
- (void)sayHello;
@end
@implementation Person (NewBehavior)
- (void)sayHello {
NSLog(@"New Hello");
}
@end
当调用[Person new] sayHello]
时,调用的是Category中实现的方法(在实际复杂情况下,方法决议等机制会影响最终调用哪个sayHello
方法,但原则是不会覆盖)。
- 不能声明
@property
的@synthesize
和@dynamic
:在Category中可以声明@property
,但不能使用@synthesize
和@dynamic
。例如:
@interface Person (ExtraProperties)
@property (nonatomic, copy) NSString *hobby;
// 不能在这里写 @synthesize hobby; 或 @dynamic hobby;
@end
需要手动提供存取方法的实现来处理这个@property
。通常,在Category中声明的@property
,需要通过关联对象(Associated Objects)来实现其存储。
其他限制
- 无法添加协议(Protocol):Category本身不能添加新的协议供类遵循。如果要让类遵循新的协议,需要在类的主接口声明处添加协议遵循。例如,不能在Category中像下面这样写:
@interface Person (ExtraProtocol) <NewProtocol> // 错误,Category不能添加协议
@end
若要让Person
类遵循NewProtocol
,应在Person
类的主接口@interface Person : NSObject <NewProtocol>
处添加。