6

我正在编写一个库,它可能会被不是我的人使用。

假设我写了一个类:

有趣的类.h

@interface InterestingClass: NSObject
- (id)initWithIdentifier:(NSString *)Identifier;
@end

有趣的课堂.m

@interface InterestingClass()
- (void)interestingMethod;
@end

@implementation InterestingClass
- (id)initWithIdentifier:(NSString *)Identifier {
  self = [super init];
  if (self) {
    [self interestingMethod];
  }
  return self;
}

- (void)interestingMethod {
  //do some interesting stuff
}
@end

如果有人稍后使用该库并决定创建一个子类InterestingClass怎么办?:

有趣的子类.h

@interface InterestingSubClass: InterestingClass
@end

有趣的子类.m

@interface InterestingSubClass()
- (void)interestingMethod;
@end

@implementation InterestingSubClass
- (void)interestingMethod {
  //do some equally interesting, but completely unrelated stuff
}
@end

未来的图书馆用户可以从公共接口中看到它initWithIdentifier是超类的一个方法。如果他们重写此方法,他们可能会(正确地)假设该superclass方法应该在子类实现中调用。

但是,如果他们定义了一个方法(在子类私有接口中)无意中与超类“私有”接口中的不相关方法同名,该怎么办?如果没有他们阅读超类的私有接口,他们不会知道他们不仅创建了一个新方法,而且还覆盖了超类中的某些内容。子类实现最终可能会被意外调用,而超类在调用方法时期望完成的工作将无法完成。

我读过的所有 SO 问题似乎都表明这只是 ObjC 的工作方式,并且没有办法绕过它。是这种情况,还是我可以做些什么来保护我的“私有”方法不被覆盖?

或者,有什么方法可以限制从我的超类调用方法的范围,这样我就可以确定将调用超类实现而不是子类实现?

4

2 回答 2

3

AFAIK,你能希望的最好的就是声明覆盖必须调用 super。您可以通过将超类中的方法定义为:

- (void)interestingMethod NS_REQUIRES_SUPER;

这将在编译时标记任何不调用 super 的覆盖。

于 2014-04-08T18:55:19.077 回答
1

对于框架代码来说,处理这个问题的一个简单方法是给你所有的私有方法一个私有前缀。

您会经常在堆栈跟踪中注意到,Apple 框架调用私有方法通常以一个 under bar 开头_

如果您确实提供了一个供人们看不到您的源代码的外部使用框架,那么这才是真正值得关注的问题。

注意
不要用下划线前缀开始你的方法,因为这个约定已经被保留

于 2013-01-31T14:20:17.240 回答