如何在目标c中覆盖超类的私有方法和属性

时间:2014-03-14 11:24:25

标签: ios objective-c inheritance

使用cocoapods中的库,我想覆盖一些私有方法而不会弄乱库。

ClassInLibrary.h

@interface ClassInLibrary : UIView     
- (void)publicMethod;
@end

ClassInLibrary.m

@interface ClassInLibrary ()   
@property BOOL privateBoolean;   
@end   
@implementation ClassInLibrary  
- (void)privateMethod {
    ...
}
- (void)publicMethod {
    ...
    self.privateBoolean = YES;
    [self privateMethod];
}    
@end

我要做的是创建ClassInLibrary的子类并覆盖publicMethod。但是,由于aBooleanprivateMethod不可见,是否有任何方法可以覆盖publicMethod,因为我需要使用它们?

Subclass.m

@interface Subclass ()    
@end    
@implementation Subclass
- (void)publicMethod {
    ...
    self.privateBoolean = NO; // cannot access
    [self privateMethod]; // cannot access
}   
@end

编辑:

我同意@Anoop Vaidya,调用私有API不是一个好主意。真实案例是公共方法中的硬编码字符串,我想修改它。

Superclass.m

- (void)publicMethod {
    ...
    [self privateMethod];
    ...
    NSString *string = @"a string";
    [self doSomeThingWithTheString]; // private
    ...
} 

我无法使用[super publicMethod],因为它会再次调用privateMethod。 可能有更好,更安全的方法来实现这一目标吗?

2 个答案:

答案 0 :(得分:4)

您可以执行以下操作,但不应该这样做。

您可以使用选择器调用私有方法,但它会显示一条警告,您可以禁用它。

    SEL selector = NSSelectorFromString(@"privateMethod");
    if ([a respondsToSelector:selector]) {
        NSLog(@"yes privateMethod exists");
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self performSelector:selector];
#pragma clang diagnostic pop
    }

答案 1 :(得分:2)

您可以使用在子类中定义但在超类上定义的类别,以使属性和方法定义对子类可见。现在,您可以覆盖公共方法并使用私有部分。

你仍需要小心,如果将来更改/移动/重命名私有部分,你的代码将编译得很好。因此,在执行此类操作时,您的代码应该是防御性的,并产生有意义的错误,以便您知道发生了什么。同时确保单位/回归测试涵盖此区域。