Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 调用继承的私有方法的漂亮解决方案_Objective C_Architecture - Fatal编程技术网

Objective c 调用继承的私有方法的漂亮解决方案

Objective c 调用继承的私有方法的漂亮解决方案,objective-c,architecture,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)childWillOv

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

    //  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
@接口A:NSObject
@结束
//上午
#输入“A.h”
@实施A
-(id)init
{
self=[super init];
如果(自我){
[任性];
}
回归自我;
}
-(无效)儿童意志凌驾{
NSLog(@“childWillOverride-A”);
}
@结束
//B.h
#进口
#输入“A.h”
@接口B:A
@结束
//文学硕士
#输入“B.h”
@实施B
-(id)init
{
self=[super init];
如果(自我){
[任性];
}
回归自我;
}
-(无效)儿童意志凌驾{
[super childWillOverride];//这是不可能的
NSLog(@“childWillOverride-B”);
}
@结束

我不想将函数名移动到A.h,也不想为函数名创建新的类别或.h文件。您还有其他想法吗?

您可以使用以下代码

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

就我个人而言,我宁愿为这些受保护的方法创建一个单独的.h文件,就像苹果为
所做的那样

另一种方法(我不喜欢)是使用:

因此,你的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方法。

我使用受保护的类别来处理这类事情:

// 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

顺便说一下,我相信当你
init
这个
B
对象时,你会调用B的
childWillOverride
两次,我怀疑这是你的意图。所以
[[A alloc]init]
应该从
A
调用
childWillOverride
?而
[[B alloc]init]
应该从
B
调用
childWillOverride
,或者两者都调用?@MartinR当B的
init
调用A的
init
时,当A的
init
随后调用
[self childWillOverride]
时,它实际上会调用B的
childWillOverride的实现(随后调用A的实现)。因此,当B的
init
调用
[super init]
时,它实际上已经调用了
childWillOverride
,大概不应该再这样做了。@Rob:我的问题是为了让OP知道他想要实现什么。好主意,但这会导致堆栈溢出:)不,它不是,我们称之为“超级非自我”。@mohamede1945-对不起,但flatronka是正确的。虽然这是一种不错的探索方法,但并不奏效。
super
调用有效地告诉运行时在继承层次结构中的什么点开始搜索方法,在您的示例中,正在搜索的方法是
performSelector:
。无论您是从
self
还是
super
开始搜索
performSelector:
都会找到相同的方法,而该方法将从
self
开始自己的搜索……我不知道苹果正以这种方式解决问题。我不喜欢在B中定义私有A方法的解决方案。@flatronka-你试图做一些你不应该做的事情,重写私有方法,所以你会以这样或那样的方式弄脏你的手。Rob展示的解决方案的好处是非常干净,你为什么不喜欢呢?另一种解决方案是调用运行时方法来定位该方法的实际实现,并直接调用它——这要复杂得多。