2010-06-10 2 views
0

좋습니다, 그래서 Objective-C를 사용하고 있습니다. 자, 내가 가지고 말 :Obj-c 메서드 재정의/다형성 문제

TopClass : NSObject 
- (int) getVal {return 1;} 
MidClass : TopClass 
- (int) getVal {return 2;} 
BotClass : MidClass 
- (int) getVal {return 3;} 

나는 다음 NSMutableArray에 개체를 넣고 밖으로 데리고. 내가 적절한 개체 유형에 GETVAL의 FUNC를 실행하고 싶은,하지만 난

id a = [allObjects objectAtIndex:0]; 
if ([a isKindOfClass:[TopClass class]]) 
{ 
    int i; 
    i = [a getVal]; 
} 

을 넣을 때 컴파일러는 실제 개체 유형을 판별 할 수 아마도 때문에 내가 먼저 GETVAL (라고 여러 방법에 대한 경고가 런타임까지). 하지만 더 진지하게 나는 "무언가가 무시되어서는 안되는 무효 값"이라는 오류가 발생하고 컴파일되지 않습니다.

[a getVal]의 반환 값을 사용하지 않으면 예를 들어 잘 컴파일됩니다.

[a getval]; //obviously no good if I want to use the return value 

isMemberOfClass 문을 사용하여 함수를 실행하기 전에 클래스에 객체를 캐스팅하는 경우에도 작동합니다.

if ([a isMemberOfClass:[BotClass]) i = [(BotClass*) a getVal]; 

하지만 꼭 필요한 기능을 사용해서는 안됩니다. 그렇지 않으면 모든 단일 하위 클래스에 대한 성명서를 작성해야하며, 새 하위 클래스를 추가하는 경우 새 줄을 추가해야합니다. 새 하위 클래스를 추가하면 메서드 오버라이드 점이 무의미합니다.

분명히 더 좋은 방법이 있습니까?

+1

Objective-C'-getSomething'에서 메소드의 이름을 지정하면 안됩니다. 이름을'-something'으로 지정하십시오. –

답변

1

BotClass가 MidClass이고 MidClass가 TopClass이므로 a의 유형을 TopClass*으로 설정할 수 있습니다.

TopClass* a = [allObjects objectAtIndex:0]; 
if ([a isKindOfClass:[TopClass class]]) { 
    int i; 
    i = [a getVal]; 
} 

더 좋은 방법은 @interface#import을받는 -getVal를 추가하는 것입니다. 그렇다면 컴파일러는 int을 반환 할 가능성이 높고 aid 인 경우에도 불평하지 않음을 알 수 있습니다. 하지만 메소드 이름이 다른 메소드와 일치하지 않는지 확인하십시오.

은 (BTW, ObjC에서, 게터는 -getFoo로 명명되지 않습니다 컨벤션 단지 -foo를 호출한다..)

+0

완벽한 의미의 완벽한. 나는 거의 그것을 시도해 왔지만 배열에서 캐스팅으로 메서드를 돌리는 것은 TopVal의 메서드만을 사용했다. 이 방법은 컴파일러가 무엇을 기대할지를 알고 있다고 가정하지만 서브 클래스를 무시하도록 캐스트에 의해 제한되지 않습니다. 고마워요. – Rod

+0

먼저 TopClass 변수에 할당하고 그 객체가 정말로 * 그런 종류인지 아닌지를 확인하는 것이 재미있는 아이디어라고 말하고 싶습니다. 그것은 단지 포인터 일뿐입니다 (NSArray * a를 사용할 수도 있고 경고와 함께 컴파일되지만이 경우에는 작동합니다). 그러나 코드 의도를 숨기는 것이 좋습니다. :-) – Eiko

0

귀하의 코드가 경고없이 컴파일 :

#import <Foundation/Foundation.h> 


@interface TopClass : NSObject 
{ 
} 

- (int) getVal; 

@end 

@interface MidClass : TopClass 
{ 
} 

- (int) getVal; 

@end 

@interface BotClass : MidClass 
{ 
} 

- (int) getVal; 

@end 


@implementation TopClass 

- (int) getVal { 
    return 1; 
} 

@end 

@implementation MidClass 

- (int) getVal 
{ 
    return 2; 
} 

@end 

@implementation BotClass 

- (int) getVal 
{ 
    return 3; 
} 

@end 


int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSMutableArray *array = [NSMutableArray array]; 

    [array addObject:[[[TopClass alloc]init]autorelease]]; 
    [array addObject:[[[MidClass alloc]init]autorelease]]; 
    [array addObject:[[[BotClass alloc]init]autorelease]]; 

    for (int objectNumber = 0; objectNumber < [array count]; objectNumber++) { 
     id a = [array objectAtIndex:objectNumber]; 
     if ([a isKindOfClass:[TopClass class]]) 
     { 
      int i = [a getVal]; 
      NSLog(@"%d",i); 
     }  
    } 

    [pool drain]; 
    return 0; 
} 

테스트 "isKindOfClass "이 경우 MidClass와 BotClass가 TopClass에서 상속하므로 항상 true입니다.

컴파일러에서 호출하는 메서드 서명을 알고 있습니까?