我有以下设计:
@protocol SomeProtocol <NSObject>
@optional
- (void)someMethod;
@end
@interface SomeObject : NSObject <SomeProtocol>
@end
我想为我的协议提供someMethod
的默认工具,所以我创建了一个类似的类别:
@interface SomeObject (SomeCategory) <SomeProtocol>
- (void)someMethod;
@end
@implementation SomeObject (SomeCategory)
- (void)someMethod
{
// default implementation for all classes implementing the protocol SomeProtocol
}
@end
现在我还想留下实现此方法的自定义实现的可能性。如果我直接在SomeObject
类上实现,如下所示:
@interface SomeObject <SomeProtocol>
- (void)someMethod;
@end
@implentation SomeObject
- (void)someMethod
{
// custom implementation for SomeObject class
}
@end
此实现似乎优先于类别方法。但Apple文档说:
如果类别中声明的方法的名称与方法相同 在原始类中,或在另一个类别中的方法相同 class(甚至是超类),行为未定义为哪个 方法实现在运行时使用。
我还没有想到其他可能更好的可能性(比如使用基类和子类)但是我在这里做的是一个好的设计还是必须导致未定义的行为?
提前感谢您的帮助
答案 0 :(得分:1)
关于此事的文件不太清楚。除了到目前为止所提到的,在文档中的其他一些点上,它说:“当一个类别覆盖一个继承的方法时,该类别中的方法可以像往常一样通过消息调用继承的实现到超级。 ,如果一个类别覆盖了类别类中已经存在的方法,则无法调用原始实现“ - 我将其视为”类别实现将始终运行而不是原始实现“。
我以前读过这篇文章,但直到现在才发现,但this SO answer已经提到过。
就个人而言,我经常使用类别覆盖方法,到目前为止,它给我带来了麻烦。但是,因为我知道我“杀死”了原始实现,所以我只关注这样做的方法,可以安全地假设该类继承了超类的原始实现。
例如,我认为在touchesBegan:withEvent:
上的类别中覆盖UIView
是安全的,因为该方法已从UIResponder
继承而且原始实现仍未受影响且可以(并且应该通过在类别的实施中调用super
来达到。
据我所知,抽象或空实现也可以安全地覆盖。例如,我已经覆盖awakeFromNib
中的UIScrollView
以克服滚动视图不能根据实际内容大小自行设置其contentSize属性的问题,以防它在Interface Builder中创建:
@implementation UIScrollView (MyHandyCategory)
-(void)awakeFromNib {
[self autoResizeContent];
}
-(void)autoResizeContent {
NSArray *subViews = [self subviews];
UIView *contentView = [subViews objectAtIndex:0];
[self setContentSize:contentView.frame.size];
}
@end
如果你想知道为什么我不把autoresize代码放在awakeFromNib中 - 我希望能够在其他场合调用autoresize。在我的实际类别中,awakeFromNib中有更多代码,我不一定要与自动调整代码一起运行。
答案 1 :(得分:0)
好吧,既然Apple说这种行为是不明确的,那么我认为这是一个坏主意。它今天可能有用,但不能保证明天会有效。
我不确定你想要做什么有一个很好的选择,但更好的选择是调查混合。
这允许您将一个类的选择器替换为另一个类。以下是一个很好的介绍,它可以做些什么以及需要注意的一些方面 - https://stackoverflow.com/a/8636521/3096507。