创建具有不同子类属性的子类 [英] Create subclass with different subclass property
问题描述
说我有这个班
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
@end
我想创建CustomClass的子类,但这是要抓住的地方
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
您可以想象的问题是,当我初始化ASubClassCustomClass并调用它的超级初始化程序(因为需要其他属性)时,将创建不可变的nicestArrayEver. /p>
注意:这只是一个例子,真正的实现调用了一个繁重的创建和真正定制的子类(不是NSArray).
合成时,您可以通过使用不同的后备变量使其工作,如下所示:@synthesize nicestArrayEver = nicestArrayEverSubClass_;
#import <Foundation/Foundation.h>
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
@end
@implementation CustomClass
@synthesize nicestArrayEver ;
-(id)init
{
if (self = [super init]) {
nicestArrayEver = [[NSArray alloc] init];
}
return self;
}
@end
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
@implementation ASubClassCustomClass
@synthesize nicestArrayEver = nicestArrayEverSubClass_;
-(id)init{
if (self = [super init]) {
nicestArrayEverSubClass_ = [[NSMutableArray alloc] init];
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
CustomClass *c1 = [[[CustomClass alloc] init] autorelease];
ASubClassCustomClass *c2 = [[[ASubClassCustomClass alloc] init] autorelease];
NSLog(@"%@", NSStringFromClass([[c1 nicestArrayEver] class]));
NSLog(@"%@", NSStringFromClass([[c2 nicestArrayEver] class]));
}
return 0;
}
输出
2012-05-27 01:59:16.221 NicestArray[2312:403] __NSArrayI
2012-05-27 01:59:16.225 NicestArray[2312:403] __NSArrayM
另一种方法可能是在基类中有2个init方法,一个将实例化属性,一个将不会实例化,但是将任务留给子类-这将阻止您仅创建昂贵的对象扔掉它们.
现在,可以使用第二个init直接实例化基类,并使其进入false状态.您可以通过使用isMemberOfClass:
检查自身类的类型来避免这种情况,如果类类型是基类,则抛出错误.
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
-(id)initWithoutArray;
@end
@implementation CustomClass
@synthesize nicestArrayEver ;
-(id) initWithoutArray
{
if (self = [super init]) {
if ([self isMemberOfClass:[CustomClass class]]) {
[NSException raise:@"AbstractMethodCall" format:@"%@ should be called only from Subclasses of %@", NSStringFromSelector(_cmd), NSStringFromClass([self class])];
}
}
return self;
}
-(id)init
{
if (self = [super init]) {
nicestArrayEver = [[NSArray alloc] init];
}
return self;
}
@end
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
@implementation ASubClassCustomClass
@synthesize nicestArrayEver = nicestArrayEverSubClass_;
-(id)init{
if (self = [super initWithoutArray]) {
nicestArrayEverSubClass_ = [[NSMutableArray alloc] init];
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
CustomClass *c1 = [[[CustomClass alloc] init] autorelease];
ASubClassCustomClass *c2 = [[[ASubClassCustomClass alloc] init] autorelease];
NSLog(@"%@", NSStringFromClass([[c1 nicestArrayEver] class]));
NSLog(@"%@", NSStringFromClass([[c2 nicestArrayEver] class]));
//this works, as it is the subclass
ASubClassCustomClass *shouldWork = [[[ASubClassCustomClass alloc] init] autorelease];
// ouch!
CustomClass *shouldCrash = [[[CustomClass alloc] initWithoutArray] autorelease];
}
return 0;
}
Say I have this Class
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
@end
And I want to create a subClass of CustomClass, but here is the catch
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
The issue as you can imagine is that when I initialize ASubClassCustomClass and call it's super initializer (since there is other properties required) the inmutable nicestArrayEver is created.. how can I avoid it's creation so I can set the mutable one?
Note: This is just an example, the real implementation calls a heavy to create and really customized subclass (is not an NSArray).
You can make it work, by using different backing variables, when synthesizing it looks like this: @synthesize nicestArrayEver = nicestArrayEverSubClass_;
#import <Foundation/Foundation.h>
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
@end
@implementation CustomClass
@synthesize nicestArrayEver ;
-(id)init
{
if (self = [super init]) {
nicestArrayEver = [[NSArray alloc] init];
}
return self;
}
@end
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
@implementation ASubClassCustomClass
@synthesize nicestArrayEver = nicestArrayEverSubClass_;
-(id)init{
if (self = [super init]) {
nicestArrayEverSubClass_ = [[NSMutableArray alloc] init];
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
CustomClass *c1 = [[[CustomClass alloc] init] autorelease];
ASubClassCustomClass *c2 = [[[ASubClassCustomClass alloc] init] autorelease];
NSLog(@"%@", NSStringFromClass([[c1 nicestArrayEver] class]));
NSLog(@"%@", NSStringFromClass([[c2 nicestArrayEver] class]));
}
return 0;
}
output
2012-05-27 01:59:16.221 NicestArray[2312:403] __NSArrayI
2012-05-27 01:59:16.225 NicestArray[2312:403] __NSArrayM
Another approach could be to have 2 init methods in the base class, one, that will instantiate the property and one, that won't, but leaves that task for the child class — this will prevent you from creating expensive objects just to throw them away.
Now the base class could get instantiated directly with the second init and go to a false state. You can avoid this by checking the self class type with isMemberOfClass:
, and throw an error, if the class type is the base class.
@interface CustomClass : NSObject
@property (nonatomic, strong) NSArray * nicestArrayEver;
-(id)initWithoutArray;
@end
@implementation CustomClass
@synthesize nicestArrayEver ;
-(id) initWithoutArray
{
if (self = [super init]) {
if ([self isMemberOfClass:[CustomClass class]]) {
[NSException raise:@"AbstractMethodCall" format:@"%@ should be called only from Subclasses of %@", NSStringFromSelector(_cmd), NSStringFromClass([self class])];
}
}
return self;
}
-(id)init
{
if (self = [super init]) {
nicestArrayEver = [[NSArray alloc] init];
}
return self;
}
@end
@interface ASubClassCustomClass : CustomClass
@property (nonatomic, strong) NSMutableArray * nicestArrayEver;
@end
@implementation ASubClassCustomClass
@synthesize nicestArrayEver = nicestArrayEverSubClass_;
-(id)init{
if (self = [super initWithoutArray]) {
nicestArrayEverSubClass_ = [[NSMutableArray alloc] init];
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
CustomClass *c1 = [[[CustomClass alloc] init] autorelease];
ASubClassCustomClass *c2 = [[[ASubClassCustomClass alloc] init] autorelease];
NSLog(@"%@", NSStringFromClass([[c1 nicestArrayEver] class]));
NSLog(@"%@", NSStringFromClass([[c2 nicestArrayEver] class]));
//this works, as it is the subclass
ASubClassCustomClass *shouldWork = [[[ASubClassCustomClass alloc] init] autorelease];
// ouch!
CustomClass *shouldCrash = [[[CustomClass alloc] initWithoutArray] autorelease];
}
return 0;
}
这篇关于创建具有不同子类属性的子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!