2012-02-05 2 views
1

의 난과 같이 두 개의 클래스가 있다고 가정 해 봅시다 :수퍼 클래스 속성을 하위 클래스로 복사하는 방법은 무엇입니까?

Car 
{ 
    NSInteger wheels; 
    NSInteger bumpers; 
} 

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


Lexus : Car 
{ 
    GPS *navigation; 
} 

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

carWithData:carData에서 변수로 채워 Car의 인스턴스를 생성하는 간단한 도우미 방법입니다. Lexus 버전은 navigation 데이터도 설정합니다.

carWithDataCar의 코드를 복제하지 않고 어떻게 보이나요?

답변

5

이것은 init 메소드에 init…super의 구현을 호출하여 수행됩니다

//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]Lexus 클래스의 개체를 반환하지만 컴파일러는 Car을 예상하므로 컴파일러는 알지 못합니다. 서브 클래스의 구현은 여기에

- (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]; 
} 
+0

아, 나는 당신이 실제로 클래스 메소드 내에서'[self alloc]'을 할 수 있는지 모른다. 나는이 대답이 가장 깨끗하다고 ​​생각한다. – pixelfreak

+0

@pixelfreak : 물론 가능합니다. C++과는 달리 Objective-C에는 클래스 메소드 호출에 대한 제한이 없습니다. – Regexident

+1

@pixelfreak : Objective-C에서'self'는 ** 인스턴스 메소드 **에있을 때의 ** 인스턴스 객체 **와 ** 클래스 메소드 **에있을 때 ** 클래스 객체 **를 참조합니다. Objective-C 클래스는 실제로 객체 자체임을 기억하십시오. – Regexident

0

당신은 같은 다른 서명 방법을 정의 할 것 내 해결책이 될거야 :

당신이 [Lexus carWithCarData:myData]를 호출 할 때 16,
// 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; 
} 

그래서, 그것은 Lexusinit 방법이 아닌 Car 년대를 호출 끝납니다.

+0

'Lexus'가'Car'의 서브 클래스라면, 헤더 선언을 원하는대로 재 정의 할 수 있습니다. –

+0

예 (적어도 경고를 일으킬 것이라고 생각했는데 그렇게 보이지는 않습니다.)하지만 약간 변경된 코드를 반복하면 좋지 않은 것처럼 들립니다. –

0

과 같을 것이다 대신

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

를 사용해야합니다

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

:

+0

'initWith ... :/fooWith ... :'(예 :'Car *')에 클래스 반환 유형을 지정하지 말고 대신 항상'id'를 반환하십시오. – Regexident

0

NSCoding 프로토콜과 NSKeyedArchiver을 사용하면보다 일반적인 방법이 있습니다.

당신이 당신의 서브 클래스에 복사 할 개체는 다음과 완전히 합법적이고 안전 트릭을 사용할 수있는 많은 NS ... 기반 클래스의 경우입니다 NSCoding 프로토콜을 구현하는 경우 :

// 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 
관련 문제