【问题标题】:How to avoid subclass inadvertently overriding superclass private method如何避免子类无意中覆盖超类私有方法
【发布时间】:2013-01-15 16:05:18
【问题描述】:

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

假设我写了一个类:

InterestingClass.h

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

InterestingClass.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 的子类怎么办?:

InterestingSubClass.h

@interface InterestingSubClass: InterestingClass
@end

InterestingSubClass.m

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

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

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

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

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

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

【问题讨论】:

标签: objective-c objective-c-category class-extensions


【解决方案1】:

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

- (void)interestingMethod NS_REQUIRES_SUPER;

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

【讨论】:

  • 这是一个非常可行(并且可能看起来更干净)的替代方法,可以在我所有的方法名称之前添加某种独特的字符串。干杯!
  • 根据this 的讨论,可以通过#pragma clang diagnostic push \ #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" \ <INSERT METHOD HERE> \ #pragma clang diagnostic pop 消除clang 警告
  • @Clay,这对我来说没有解决。这只会添加一个警告!
【解决方案2】:

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

您会经常在堆栈跟踪中注意到,Apple 框架调用私有方法通常以下划线 _ 开头。

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

注意
不要使用下栏前缀开始您的方法,因为此约定已被保留

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-08
    • 2012-08-12
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2018-07-08
    相关资源
    最近更新 更多