【发布时间】:2011-07-10 11:23:51
【问题描述】:
我想去那里。说真的,如何以“Apple”的方式实现纯虚拟方法?您是否在基类中使用协议并在这些方法上引发异常?
【问题讨论】:
-
对于来自强大的 OO C++ 背景的人来说,这是一个很好的问题。
标签: objective-c methods pure-virtual
我想去那里。说真的,如何以“Apple”的方式实现纯虚拟方法?您是否在基类中使用协议并在这些方法上引发异常?
【问题讨论】:
标签: objective-c methods pure-virtual
当你在 Objective-C 中编程时,你需要清除脑海中的虚方法之类的东西。您不会在 Objective-C 对象上调用方法,而是向它们发送消息。对象要么响应消息,要么不响应消息,但由于动态绑定,直到运行时您才能知道这一点。
因此,您可以在基础对象上声明方法而不提供实现,没问题(编译器警告除外),但是当您使用此类方法直接实例化对象时,您不能让编译器标记并且它不会在运行时抛出错误,除非您实际将该消息发送到对象。
创建“虚拟”基类的最佳方式(在我看来)是声明该方法并为其提供一个引发适当异常的存根实现。
【讨论】:
在 Objective-C 中,没有像 C++ 中那样的纯虚拟支持。
模拟是您在接口中声明了一个方法,但不在 .m 文件中实现它。当然,您会收到编译器警告,但 IIRC 您可以将其关闭。但是,如果您不在 C++ (IIRC) 中获得的子类中覆盖它们,您将不会收到警告/错误。
另一种方法是仅使用 NSAssert(NO, @"Subclasses need to overwrite this method"); 正文来实现它们。不过,您只能在运行时而不是编译时捕获它。
【讨论】:
根据您正在做的事情,委托模式可能比子类更合适,其中委托被定义为id<YourDelegateProtocol>。如果委托协议中所需的方法未实现,编译器将生成警告。
在 Objective-C 中通常避免子类化,因为对象不能从多个超类继承,但它们可以实现多个协议。
【讨论】:
你应该使用:
- (void)doesNotRecognizeSelector:(SEL)aSelector method.
正如 Apple 所说,这里:https://developer.apple.com/library/mac/#documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
【讨论】:
你有几个选择,但你在正确的轨道上。
ObjC 不直接支持这一点,强制子类实现协议是编译时检查它的最佳方式。
“秘密”在基类中实现该方法并断言是我所做的,以确认子类在运行时已正确子类化。有些人对断言有复杂的感觉,或者必须让它们保持活跃,所以这并不总是一个好的解决方案。
您还可以强制子类使用特定的类构造函数和初始化序列,然后在返回实例之前验证它们是否已实现所需的一切,以防编译器警告无法解决。
但是 ObjC 缺少一些语言特性,这些特性允许客户在脚下开枪,或者解决他们希望的问题......你不应该太拘泥于强制执行它。
注意:异常在 ObjC 中非常少见(也有点不安全)。
【讨论】:
虚拟方法是一种方法,其行为可以在继承类中被具有相同签名(即具有相同参数数量和参数类型的相同名称)的函数覆盖。
示例:-
@implementation BaseClass
-(void)viewDidLoad
{
[self virtualMethod:123];
}
-(void)virtualMethod:(int)param
{
//implement this method in subclass
}
@end
/////////////////////////////////////// /////
@interface ChildClass:BaseClass
@end
@implementation ChildClass
-(void)virtualMethod:(int)param
{
NSLog(@"There is no keyword "Virtual" in Objective C.");
}
@end
输出:-
“Objective C 中没有关键字“Virtual”。”
【讨论】: