假设我有一个名为“Node”的类,它有一个方法“addChild”
@interface Node : NSObject
-(void) addChild:(Node *)n;
我有一个名为“Sprite”的子类,它不应响应此方法。
@interface Sprite : Node
我知道我可以做这样的事情:
@implementation Sprite
-(void) addChild:(Node *)n {
NSLog(@"Don't call addChild on a Sprite!");
}
或
-(void) addChild:(Node *)n {
NSAssert(NO, @"Don't call addChild on a Sprite!");
}
但是有没有办法声明子类不响应这个方法,让编译器抛出错误呢?在这种情况下,出现编译器错误要比出现运行时错误好得多。
编辑
我意识到这违反了 Liskov 替换原则。但是在 Apple 的文档中是这样的:
“任何 doesNotRecognizeSelector: 消息通常只由运行时系统发送。但是,它们可以在程序代码中使用以防止方法被继承。例如,NSObject 子类可能通过重新声明放弃复制或初始化方法实现它以包含一个 doesNotRecognizeSelector: 消息...”
我不明白为什么抛出运行时错误而不是编译时错误会更不违反这一原则。
最佳答案
没有。
OOP 中有一个原则叫做 Liskov substitution principle其中指出,您必须始终能够用子类的实例替换原始类的实例,而不会改变相关程序的预期行为。在您的情况下,您希望节点响应 addChild:
;为了服从 LSP,我们必须让 Sprites 也响应 addChild:
。
这并不是说您无能为力。当您向它们发送 addChild:
时,您可以让 Sprites 抛出异常,或者让它们默默地忽略它,但我认为您真正想要的是让 Node 和 Sprite 成为同一父类的不同子类- 我们称它为抽象节点。您会将大部分逻辑从 Node 移至 AbstractNode,然后只需在 Node 上实现 addChild:
。
关于ios - 有没有办法让子类不响应其父类(super class)实现的方法,并让编译器抛出错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19839130/