如何将超类属性复制到子类?

时间:2012-02-05 20:55:32

标签: iphone objective-c ios ipad

假设我有两个这样的类:

Car
{
   NSInteger wheels;
   NSInteger bumpers;
}

+ (Car *)carWithData:(NSDictionary *)carData;


Lexus : Car
{
   GPS *navigation;
}

+ (Lexus *)carWithData:(NSDictionary *)carData;

carWithData:是一个简单的帮助器方法,它创建一个Car的实例,其中填充了来自carData的变量。雷克萨斯的版本也会设置navigation数据。

如果没有重复carWithData的代码,雷克萨斯会Car如何看待?

4 个答案:

答案 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…,而不是idCar。 设置代码的方式最终会导致转换问题,其中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