0

假设我有一个名为的类和两个名为and的Parent派生类。Child1Child2

@interface Parent :  NSObject {
  NSString *fooVariable;
  -(void)foo; 
}
@end

@interface Child1 :  Parent {
-(void)bar1;
}
@end

@interface Child2 :  Parent {
-(void)bar2;
}
@end

现在想象我有一个方法被调用,在某些情况foo下我想将它作为参数传递给. 根据我想调用方法或.Child1Child2bar1bar2

如何在 Objective-c 中实现这一点?

我试过的:

我决定使用以下签名和实现:

-(void)fooWithObject:(Parent *)instance{
    if ([instance isKindOfClass:[Child1 class]]){
        [instance bar1];
    }
    else{
        [instance bar2];
    }
}

所以现在我可以这样做:

Parent *instance = [[Child1 alloc] init];

//This call is supposed to lead to an invocation of bar1 inside the foo method
[self fooWithObject:instance]

instance = [[Child2 alloc] init];
//This call is supposed to lead to an invocation of bar2 inside the foo method
[self fooWithObject:instance]

不幸的是,当我尝试编译我的代码时,编译器抱怨在我的父接口中没有声明方法 bar1(或 bar2)。

根据一些在线教程,您可以执行以下操作,因此理论上我的方法应该有效:

NSArray *anotherArray = [NSMutableArray array];
// This mutable-only method call is valid but
// produces a compile-time warning
[anotherArray addObject:@"Hello World"];
4

4 回答 4

3

一个简单的解决方案是在 Parent 和 children 中声明一个 bar 函数。然后将根据传递的类调用适当的 bar 函数。您可以使用 isKindOfClass 函数,但这会破坏继承的美感。

于 2013-08-17T21:39:18.970 回答
3

如果你认为你需要这样做(并且你必须问),那么你没有正确使用多态性。在这种特殊情况下,您应该在两个孩子中重写fooWithObject:并为该实例调用适当的方法。但听起来你的班级结构可能有更深层次的问题。

于 2013-08-17T21:45:15.990 回答
3

您快到了。在类型检查之后,您也可以安全地强制转换并使编译器满意:

-(void)fooWithObject:(Parent *)instance {

    if ([instance isKindOfClass:[Child1 self]]) {
        Child1 *child1Instance = (Child1 *)instance;
        [child1Instance bar1];
    } else {
        Child2 *child2Instance = (Child2 *)instance;
        [child2Instance bar2];
    }
}
于 2013-08-17T22:03:31.007 回答
1

我倾向于(a)将这两种bar方法命名为相同的;(b) 或者为 定义一个bar函数Parent,或者使用一个协议:

@protocol Bar <NSObject>
- (void)bar;
@end

@interface Parent : NSObject {
  NSString *fooVariable;
}
-(void)foo; 
@end

@interface Child1 :  Parent <Bar>
@end

@interface Child2 :  Parent <Bar>
@end

然后有一个方法:

-(void)fooWithObject:(id<Bar>)instance {
    [instance bar];
}

如果您真的需要bar1并且bar2完全不同的名称(这是真正抽象的方法名称使问题不太清楚的一点),那么您可以执行以下操作:

@interface Parent : NSObject {
  NSString *fooVariable;
}
-(void)foo; 
@end

@interface Child1 :  Parent
- (void)bar1;
@end

@interface Child2 :  Parent
- (void)bar2;
@end

接着,

-(void)fooWithObject:(Parent *)instance {
    if ([instance isKindOfClass:[Child1 class]]) {
        [(Child1 *)instance bar1];
    }
    else if ([instance isKindOfClass:[Child1 class]]) {
        [(Child2 *)instance bar2];
    }
}

或者

-(void)fooWithObject:(Parent *)instance {
    if ([instance respondsToSelector:@selector(bar1)]) {
        [(Child1 *)instance bar1];
    }
    else if ([instance respondsToSelector:@selector(bar2)] {
        [(Child2 *)instance bar2];
    }
}
于 2013-08-17T22:04:17.797 回答