Objective-c:在基类上调用[self message]是调用后代方法

Nil*_*oct 4 inheritance objective-c superclass

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

我有这两个类:

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

@implementation ShoutingPerson : Person

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

@end
Run Code Online (Sandbox Code Playgroud)

这是造成循环引用调用,因为saySomething一直被呼吁子类.

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

Jon*_*pan 10

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

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

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

这是说话的人.双方-saySomething:-yellSomething:呼吁通过它,而不是直接称呼对方.然后子类可以安全地覆盖任一方法来调用另一个,或者调用vocalizeSomething:loudly:而不创建无限循环.


Wad*_*kis 6

正如乔纳森所说,如果可能的话,你真的应该避免这种情况.需要此功能只是一个糟糕的设计.如果你的基类是为了被继承,它的文档应阐明哪些方法必须被覆盖和其他人可能会被覆盖.应该覆盖其他任何东西,以避免这样的问题.

也就是说,如果你处于一个非常不寻常的情况,那就是必要的(也许你不能使用你无法重构的第三方代码),这是可能的.但它并不漂亮.在构造指向和的struct objc_super实例之后,需要手动调用objc_msgSendSuperobjc_msgSendSuper_stret.selfYourBaseClass

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