Objective-C指向实现协议的类的指针

Objective-C指向实现协议的类的指针,objective-c,polymorphism,Objective C,Polymorphism,我有三个实现相同协议的类,还有一个不实现协议的父类。通常我会将协议作为父类中的纯虚拟函数,但我找不到Objective-C方法来实现这一点 我希望通过在超类中声明纯虚函数,然后让子类实现这些函数,从而在这些子类上利用多态性。然而,我发现唯一的Objective-C方法是让每个孩子明确地决定实现一个协议,当我这样做时,超类不知道孩子们将实现该协议,因此到处都有编译时警告 一些伪代码,如果没有意义: @interface superclass: NSObject {} @interface chi

我有三个实现相同协议的类,还有一个不实现协议的父类。通常我会将协议作为父类中的纯虚拟函数,但我找不到Objective-C方法来实现这一点

我希望通过在超类中声明纯虚函数,然后让子类实现这些函数,从而在这些子类上利用多态性。然而,我发现唯一的Objective-C方法是让每个孩子明确地决定实现一个协议,当我这样做时,超类不知道孩子们将实现该协议,因此到处都有编译时警告

一些伪代码,如果没有意义:

@interface superclass: NSObject
{}

@interface child1: superclass<MyProtocol>
{}

@interface child2: superclass<MyProtocol>
{}

我发现,在Objective-C中实现纯虚拟函数的唯一好方法是使用
[self-doesNotRecognizeSelector:_cmd]在父类中,但这并不理想,因为它会导致运行时错误而不是编译时错误。

Objective-C开发人员在这些情况下通常使用动态检查而不是编译时检查,因为语言和框架非常支持它。例如,您可以这样编写您的方法:

- (void)someMethod
{
    // See if the object in currentView conforms to MyProtocol
    //
    if ([currentView conformsToProtocol:@protocol(MyProtocol)])
    {
        // Cast currentView to the protocol, since we checked to make
        // sure it conforms to it. This keeps the compiler happy.
        //
        [(SuperClass<MyProtocol> *) currentView protocolMethod];
    }
}
- (id) myProtocolMethod {
  NSAssert(NO, [NSString stringWithFormat:@"-[%@ %@] must be overridden", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]);
  return nil;
}
@property (nonatomic, retain) superclass<MyProtocol> *currentView;
-(void)someMethod
{
//查看currentView中的对象是否符合MyProtocol
//
if([currentView conformsToProtocol:@protocol(MyProtocol)])
{
//将currentView强制转换为协议,因为我们检查了
//确保它符合它。这使编译器感到高兴。
//
[(超类*)currentView协议方法];
}
}

就我个人而言,我会在超类上实现协议,但实现如下方法:

- (void)someMethod
{
    // See if the object in currentView conforms to MyProtocol
    //
    if ([currentView conformsToProtocol:@protocol(MyProtocol)])
    {
        // Cast currentView to the protocol, since we checked to make
        // sure it conforms to it. This keeps the compiler happy.
        //
        [(SuperClass<MyProtocol> *) currentView protocolMethod];
    }
}
- (id) myProtocolMethod {
  NSAssert(NO, [NSString stringWithFormat:@"-[%@ %@] must be overridden", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]);
  return nil;
}
@property (nonatomic, retain) superclass<MyProtocol> *currentView;

这样,如果您忘记重写具体子类中的方法,它应该立即变得明显。

或者您可以使用以下方法

if ([unknownObject conformsToProtocol:@protocol(MyProtocol)])
   [unknownObject performSelector:@selector(methodInProtocol)];
如果您只想抑制警告,请不要执行以下操作

if ([unknownObject conformsToProtocol:@protocol(MyProtocol)])
   [unknownObject methodInProtocol];  // will cause warning

PerformSelect:仅当参数数为零或一时才起作用。NSInvocation可以实现更灵活的调用。

我可以通过使
超类*currentView
属性如下所示,让编译器正确地警告我:

- (void)someMethod
{
    // See if the object in currentView conforms to MyProtocol
    //
    if ([currentView conformsToProtocol:@protocol(MyProtocol)])
    {
        // Cast currentView to the protocol, since we checked to make
        // sure it conforms to it. This keeps the compiler happy.
        //
        [(SuperClass<MyProtocol> *) currentView protocolMethod];
    }
}
- (id) myProtocolMethod {
  NSAssert(NO, [NSString stringWithFormat:@"-[%@ %@] must be overridden", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]);
  return nil;
}
@property (nonatomic, retain) superclass<MyProtocol> *currentView;
@property(非原子,保留)超类*currentView;

这取决于是否所有子类都应符合协议;不太清楚Winder在想什么。但我绝对不会把这些断言放在我的产品代码中。我宁愿提供空的方法,也可能记录一个警告。事实上,我会建议相反的做法:考虑让协议方法是可选的,并且执行运行时检查,但是再一次,它实际上取决于意图是什么。这是我想要的行为,只是编译器错误而不是运行时错误。不过,Objective-C似乎没有办法做到这一点。当然,使用
respondsToSelector:@selector(protocolMethod)更可靠
…如果协议有可选的方法,这是必要的。我不鼓励像这样使用运行时类型信息-这不太可能是一种真正的情况,即您在编译时不太清楚对象的类型,无法避免这样做。我见过使用RTTI的大多数常见情况都是多余的。例外情况是在Objective-C中实现泛型类型代码,不幸的是,我们被迫使用一种根本没有编译器能够为其生成代码的效率低的机制,这仅仅是因为语言规范中没有编译时泛型(与C共享/继承自C的问题)。此外,remote Exec我认为我们Objective-C程序员不使用动态类型检查,因为“框架非常支持它”,我们使用它是因为静态类型检查系统没有足够的表达能力来放弃它。纯虚拟/抽象方法的ObjC方式似乎是“类集群”。可能是值得你调查的事情。