4

我刚开始学习这个,很抱歉,如果这有一些我仍然无法掌握的明显解决方案。

我有这两个类:

@implementation Person
-(void)saySomething:(NSString*) something {
    NSLog(@"%@",something);
}
-(void)yellSomething:(NSString*) something {
    [self saySomething:[something uppercaseString]];
}
@end

@implementation ShoutingPerson : Person

-(void)saySomething:(NSString*)something {
    [super yellSomething:something];
}

@end

这会导致循环引用调用,因为saySomething总是后代类上调用。

如何在类而不是后代类上yellSomething调用saySomething方法?Person

4

2 回答 2

10

你没有。这就是继承在 Objective-C 中的工作方式。相反,您应该在基类中记录-yellSomething:仅调用的默认实现-saySomething:。然后,不搞砸堆栈跟踪成为子类的责任。

如果您真的希望能够更改调用什么的内容,请在基类中使用第三种方法:

-vocalizeSomething: (NSString *)what loudly: (BOOL)loudly;

是会说话的人。两者都-saySomething:直接-yellSomething:调用它而不是相互调用。然后子类可以安全地覆盖任一方法来调用另一个方法,或者vocalizeSomething:loudly:在不创建无限循环的情况下调用。

于 2012-12-02T16:07:29.937 回答
6

正如乔纳森所说,如果可能的话,你真的应该避免这种情况。需要这个功能只是一个糟糕的设计。如果您的基类打算被子类化,那么它的文档应该说明哪些方法必须被覆盖,哪些方法可以被覆盖。不应覆盖其他任何内容,以避免出现此类问题。

也就是说,如果您处于非常不寻常的情况下(也许您被困在无法重构的第 3 方代码中),这是可能的。但这并不漂亮。在构造指向and的struct objc_super实例之后,您需要手动调用objc_msgSendSuperobjc_msgSendSuper_stretselfYourBaseClass

请注意,如果您来自 C++,则默认行为是相同的 - 如果您SomeFunction()从基类调用并且它是虚拟方法,则将执行子类的覆盖。您必须在调用前加上明确拼写出类的前缀,例如MyBaseClass::SomeFunction(). 在 Objective-C 中没有直接的等价物 - 我会说因为这通常是一个坏主意。

于 2012-12-02T18:00:35.353 回答