子类可以覆盖非公共方法

时间:2013-06-04 09:02:43

标签: objective-c oop

我有两个课程:BatchDownloaderSpeechDownlader

BatchDownloader是基类,SpeechDownloader继承了它。

BatchDownloader中,每当下载一个文件时,都会调用-(void)downloadComplete:task

但在SpeechDownloader中,我还想在downloadComplete:task发布通知。

我可以在SpeechDownloader的实现中编写具有相同名称的方法吗?还是有更好的方法?

感谢。

P.S。我不想让-(void)downloadComplete:task公开,因为它应该只能自己调用​​。

2 个答案:

答案 0 :(得分:12)

如果在子类中实现与超类中的私有方法同名的方法,则子类方法将在子类的实例上调用

即,如果你像这样在你的超类中实现一个方法,而不在任何地方声明它:

@implementation classA

- (void)doSomething {
    NSLog("a");
}

然后,在子类实现中,实现一个具有相同名称的方法:

@implementation subclassOfA

- (void)doSomething {
    NSLog("b");
}

当您在子类的实例上调用doSomething时,将调用子类实现而不是超类实现,因此此示例中的代码将导致“b”存在打印到控制台。

但是,如果您还想访问该方法的超类实现,可以使用:

- (void)doSomething {
    [super doSomething];
    NSLog("b");
}

这也将调用超类实现。如果您收到编译错误(由于该方法是私有的并且super似乎没有实现它),您可以使用[super performSelector:@selector(doSomething)]来完成相同的操作。

这是因为Objective-C运行时查找方法调用的方式。由于这些方法具有完全相同的方法签名(相同名称,返回类型和参数[none]),因此它们被认为是相等的,并且运行时总是在查看超类之前检查对象的类,因此它将找到子类方法实现第一

此外,这意味着你可以这样做:

classA *test = [subclassOfA new];
[test doSomething];

而且,令人惊讶的是,控制台将打印“ b ”(如果您也调用super实施,则打印“ ab ”。

答案 1 :(得分:1)

如果您使用相同的方法签名实现该方法,则会将您的实现称为“公开与否”。