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展示的解决方案的好处是非常干净,你为什么不喜欢呢?另一种解决方案是调用运行时方法来定位该方法的实际实现,并直接调用它——这要复杂得多。