调用继承的私有方法的美丽解决方案

时间:2013-06-29 11:23:12

标签: objective-c architecture

基本上我想要解决以下问题的最佳解决方案:

    //  A.h
    @interface A : NSObject

    @end

    //  A.m
#import "A.h"

@implementation A

- (id)init
{
    self = [super init];
    if (self) {
        [self childWillOverride];
    }
    return self;
}

- (void)childWillOverride {
    NSLog(@"childWillOverride - A");
}
@end
//  B.h
#import <UIKit/UIKit.h>
#import "A.h"

@interface B : A

@end

//  B.m
#import "B.h"

@implementation B

- (id)init
{
    self = [super init];
    if (self) {
        [self childWillOverride];
    }
    return self;
}

- (void)childWillOverride {
    [super childWillOverride]; // This is not possible
    NSLog(@"childWillOverride - B");
}

@end

我不想将函数名称移动到A.h,或者我不想为函数名创建新的Category或.h文件。你有其他想法吗?

3 个答案:

答案 0 :(得分:13)

就个人而言,我宁愿为那些受保护的方法创建一个单独的.h文件,就像Apple为<UIKit/UIGestureRecognizerSubclass.h>所做的那样。

另一种方法(我不喜欢)是使用private class extension

因此,你的B.m将是:

#import "B.h"

@interface A ()
- (void) childWillOverride;
@end

@implementation B

- (id)init
{
    self = [super init];
    if (self) {
        [self childWillOverride];
    }
    return self;
}

- (void)childWillOverride {
    [super childWillOverride]; // This is now possible
    NSLog(@"childWillOverride - B");
}

@end

我不喜欢以这种方式使用类扩展(在B的.m文件中定义A的私有实现很奇怪),所以我个人使用单独的.h方法。

答案 1 :(得分:1)

我为这种事情使用受保护的类别:

// A.h
@interface A : NSObject
@end

// A.m
#import "A.h"
@implementation A
- (void)subclassWillOverrideButNobodyElseWill
{
  NSLog(@"Heyyyyyy");
}
@end

// A+Protected.h
#import "A.h"
@interface A (Protected)
- (void)subclassWillOverrideButNobodyElseWill;
@end

// B.h
@interface B : A
@end

// B.m
#import "A+Protected.h"
@implmentation B
- (void)subclassWillOverrideButNobodyElseWill
{
  [super subclassWillOverrideButNobodyElseWill]
  NSLog(@"Worrrrrrld");
}
@end

// Something.m
B *b = [B new];
[b subclassWillOverrideButNobodyElseWill];

// Console results:
Heyyyyyy
Worrrrrrld

答案 2 :(得分:-2)

您可以使用以下代码

if ([super respondsToSelector:@selector(childWillOverride)]) {
    [super performSelector:@selector(childWillOverride)];
}