我正在写一个json<>模型序列化器。其中一个功能是在转换为json时忽略模型中的某些属性。我让模型实现一个- (NSArray *)ignoreProperties
方法来告诉序列化器它应该忽略哪些属性。显然它需要支持继承。但现在我仍然坚持如何正确地组合对象本身和所有超类的所有数组元素。
@protocol SerializerMapping <NSObject>
- (NSArray *)ignoreProperties;
@end
@interface BaseModel : NSObject <SerializerMapping>
@property NSString *baseProperty;
@end
@implementation BaseModel
- (NSArray *)ignoreProperties {
return nil; // nothing to ignore
}
@end
// ---
@interface SuperModel : BaseModel
@property NSString *property1;
@property NSString *property2;
@end
@implementation SuperModel
- (NSArray *)ignoreProperties {
return @[@"property1"];
}
@end
// ---
@interface AwesomeModel : SuperModel
@property NSString *property3;
@property NSString *property4;
@end
@implementation AwesomeModel
- (NSArray *)ignoreProperties {
return @[@"property3"];
}
@end
// --- serializer
AwesomeModel *obj = [AwesomeModel new];
NSArray *blackList = [obj ignoreProperties]; // only returns "property3"
显然上面的代码不起作用,但我如何实现ignoreProperties
,以便它会返回property1
和property3
?
非常糟糕的方式:
@implementation AwesomeModel
- (NSArray *)ignoreProperties {
return [[super ignoreProperties] arrayByAddingObjectsFromArray:@[@"property3"]];
}
@end
很多漏洞的可能性。如果一个子类忘记调用super
链将被破坏。或BaseModel
返回nil
,然后代码根本不起作用。
答案 0 :(得分:0)
我认为teamnorge在正确的轨道上他的代码不会像发布的那样工作,因为阵列不可变。
使您的属性成为可变数组。让基类用init init方法创建它:
在基类标题中:
@property (nonatomic, retain) NSMutableArray *ignoreProperties;
然后在你的基类的init中:
-(instanceType) init;
{
self = [super init];
if (!self)
return nil;
self.ignoreProperties = [@[@"property1"] mutableCopy];
}
在您的子类的init中:
-(instanceType) init;
{
self = [super init];
if (!self)
return nil;
[self.ignoreProperties addObject: @"property2"];
//or to add multiple objects...
NSArray *newProperties = @[@"property2", @"property3"];
[self.ignoreProperties addObjectsFromArray: newProperties];
}
为了提高效率,最好使数组不可变,并让子类的init方法将其替换为使用arrayByAddingObject
或arrayByAddingObjectsFromArray
创建的数组。 (不可变对象的系统成本低于它们的可变形式。在这种情况下,属性数组只会在类的初始化时创建一次,然后在其生命周期内持续存在。)