我使用的是第三方库,它不会公开其init方法,并且会从类级别的消息中做一些专门的I-don -t-know-what。这是否禁止我进行子类化?
我做了一个测试用例(启用了ARC)
A.H
@interface A : NSObject
@property (nonatomic, strong) NSString * bar;
-(id) initWithAbar:(NSString *) bar;
+(id) aWithBar:(NSString *) bar;
@end
A.M
#import "A.h"
@implementation A
-(id) initWithAbar:(NSString *) bar
{
self = [super init];
if (self) {
self.bar = bar;
}
return self;
}
+(id) aWithBar:(NSString *) bar
{
return [[A alloc] initWithAbar:bar];
}
@end
B.h
#import <Foundation/Foundation.h>
#import "A.h"
@interface B : A
@property (nonatomic, strong) NSString *foo;
-(id) initWithFoo:(NSString *)foo bar:(NSString *)bar;
@end
B.m
#import "B.h"
@implementation B
-(id) initWithFoo:(NSString *)foo bar:(NSString *)bar
{
self = (B*)[A aWithBar:bar]; // Still actually A, knew that by printing [self class];
if (self) {
self.foo = foo; // Error: unrecognized selector here
}
return self;
}
@end
假设我不能只调用A initWithAbar:
,我在子类A中有任何选择吗?如果A的aWithBar正在调用A的init,那么init的特别之处是什么?
答案 0 :(得分:0)
注意:
- [NSObject init]
仍然可用。如果班级的创建者非常小心,他们会覆盖init
,因此会使用默认参数调用initWithBar:
。
如果您使用运行时内省或class-dump
来查找类A
上的方法列表,那么您可以确实声明(可能在类别中)和致电- [A initWithBar:]
。
但是如果你不想做任何这些(特别是#2,因为它是一个黑客),那么为什么不创建一个类似的便利方法?这样的事情:
@implementation B
+ (B *)beeWithBar:(NSString *)bar
{
B *instance = [self aWithBar:bar];
instance.someOtherProperty = 42;
return instance;
}
@end
请注意,这仅在开发人员注意并使用aWithBar:
实施[self initWithBar:]
时才有效。如果类名是硬编码的(如您的示例所示),则无法通过调用便捷方法获取B
的实例。