假设我有两个这样的类:
Car
{
NSInteger wheels;
NSInteger bumpers;
}
+ (Car *)carWithData:(NSDictionary *)carData;
Lexus : Car
{
GPS *navigation;
}
+ (Lexus *)carWithData:(NSDictionary *)carData;
carWithData:
是一个简单的帮助器方法,它创建一个Car
的实例,其中填充了来自carData
的变量。雷克萨斯的版本也会设置navigation
数据。
如果没有重复carWithData
的代码,雷克萨斯会Car
如何看待?
答案 0 :(得分:5)
这是通过在init方法中调用super
的{{1}}实现来实现的:
init…
另请注意,//Car.m:
- (id)initWithData:(NSDictionary *)carData {
self = [super init];
if (self) {
//setup generic car properties:
self.wheels = [carData objectForKey:@"wheels"]; //example
self.bumpers = [carData objectForKey:@"bumpers"]; //example
}
return self;
}
+ (id)carWithData:(NSDictionary *)carData {
return [[[self alloc] initWithData:carData] autorelease];
}
//Lexus.m:
- (id)initWithData:(NSDictionary *)carData {
//this call to super is where the car's generic properties get initialized:
self = [super initWithWithData:carData];
if (self) {
//setup lexus car properties:
self.navigation = [carData objectForKey:@"navigation"]; //example
}
return self;
}
//there is no need to override super's [carWithData:] method as it's only a wrapper anyway.
和initWith…
方法都会返回carWith…
,而不是id
或Car
。
设置代码的方式最终会导致转换问题,其中Lexus
会返回类[Lexus carWithData:dataDict]
的对象,但编译器不知道它,因为它需要{{1} }。
答案 1 :(得分:0)
您不会使用不同的签名定义方法,如:
+ (Car *)carWithData:(NSDictionary *)carData;
+ (Lexus *)carWithData:(NSDictionary *)carData;
你应该改为使用
+ (id)carWithData:(NSDictionary *)carData;
子类的实现看起来像
- (id)initWithData:(NSDictionary *)carData;
{
self = [super initWithData:carData];
if (self) {
_navigation = [carData valueForKey:@"navigation"];
}
return self;
}
+ (id)carWithData:(NSDictionary *)carData;
{
return [[[self alloc] initWithCarData:carData] autorelease];
}
答案 2 :(得分:0)
这是我的解决方案:
// interface
-(id) initWithCarData:(NSDictionary *) carData;
+(Car *) carWithCarData:(NSDictionary *) carData;
// car implementation
-(id) initWithCarData:(NSDictionary *) carData
{
if (self = [super init])
{
// initialize car data
}
return self;
}
+(Car *) carWithCarData:(NSDictionary *) carData
{
// note that 'self' here is the current class,
// there is no need to overwrite this method in the subclass
return [[self alloc] initWithCarData:carData];
}
// lexus implementation
-(id) initWithCarData:(NSDictionary *) carData
{
// initialize the variables that the superclass recognizes
if (self = [super initWithCarData:carData])
{
// initialize the lexus data
}
return self;
}
因此,当您致电[Lexus carWithCarData:myData]
时,它最终会调用Lexus
的{{1}}方法,而不是init
。
答案 3 :(得分:0)
使用NSCoding
协议和NSKeyedArchiver
,还有另一种更通用的方式。
如果要复制到您的子类中的对象实现NSCoding
协议,这是许多基于NS ...的类的情况,可以使用以下完全合法且安全的技巧:
// Assumptions:
// copyFrom is an object of ClassA
// We have a ClassB that is a subclass of ClassA
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[copyFrom encodeWithCoder:arch]; // this archives its properties
[arch finishEncoding];
NSKeyedUnarchiver *ua = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
ClassB *ourCopy = [[ClassB alloc] initWithCoder:ua]; // this restores the properties into our new object