Objective-C 中的受保护方法

Posted

技术标签:

【中文标题】Objective-C 中的受保护方法【英文标题】:Protected methods in Objective-C 【发布时间】:2011-04-13 03:44:39 【问题描述】:

等价于什么? 我想定义只有派生类可以调用/实现的方法。

【问题讨论】:

【参考方案1】:

您既不能声明受保护的方法私有。 Objective-C 的动态特性使得实现方法的访问控制成为不可能。 (你可以通过大量 修改编译器或运行时,以严重的速度损失,但显然没有这样做。)

取自Source。

【讨论】:

虽然技术上你做不到,但你可以模拟私有变量。 Lee - 如果您在 @protected 中声明一个函数指针并在 init 方法中分配一个函数,它会起作用吗?【参考方案2】:

您可以通过执行以下操作模拟对方法的受保护和私有访问:

在类扩展中声明您的私有方法(即在类的 .m 文件顶部附近声明的未命名类别) 在 Subclass 标头中声明您的受保护方法 - Apple 在 UIGestureRecognizer 方面使用此模式(请参阅文档和对 UIGestureRecognizerSubclass.h 的参考)

正如 Sachin 所指出的,这些保护措施不会在运行时强制执行(例如在 Java 中)。

【讨论】:

关于类似 UIGestureRecognizer 的解决方案:问题是,如果某些代码导入子类,它也会导入子类标头,因此它可以访问“受保护”方法。有办法解决吗? 嗨 yonix,子类头文件的导入将在 .m 文件内完成,而不是在 .h 文件内完成,因此导入子类不会导入这些受保护的方法。 酷建议布赖恩,非常感谢!对于原始发布者,对于声明的属性,只需确保您在子类的类扩展(未命名类别)实现中使用@dynamic,以便在运行时使用父类的实现 如何查看 UIGestureRecognizerSubclass.h? 感谢您指出 Apple 的内部运作方式。我posted a full example 了解如何像Apple 在UIGestureRecognizerSubclass.h 中一样实现东西【参考方案3】:

一种选择是使用类扩展来隐藏方法。

.h:

@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

.m:

@interface SomeAppDelegate()
- (void)localMethod;
@end

@implementation SomeAppDelegate

- (void)localMethod



@end

【讨论】:

我认为您甚至不需要 .m 文件中的 @interface 声明。您可以只声明一个函数并使用它,它将被视为私有。 请注意,这仅适用于 Objective C 中的最新更新。在此之前,您必须在接口中声明该方法,否则您至少会收到警告。【参考方案4】:

这是我所做的,以使受保护的方法对我的子类可见,而无需它们自己实现方法。这意味着我没有在我的子类中收到关于实现不完整的编译器警告。

SuperClassProtectedMethods.h(协议文件):

@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end

@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end

SuperClass.m:(编译器现在会强制你添加受保护的方法)

#import "SuperClassProtectedMethods.h"
@implementation SuperClass
- (void) protectedMethod:(NSObject *)foo 
@end

子类.m:

#import "SuperClassProtectedMethods.h"
// Subclass can now call the protected methods, but no external classes importing .h files will be able to see the protected methods.

【讨论】:

protected的意思是不能被外部调用。您仍然可以调用类中定义的任何方法,无论它们是否在外部可见。 是的,我明白这一点。此方法适用于人脑,而不适用于实际编译的代码。但是 Objective-C 不允许这样做(不能从外部调用)。你可以随时performSelector 就可以了。 你也可以[(id)obj hiddenMethod]。准确地说,Objective-C 不支持受保护的方法。 这个问题是你所谓的受保护类不能广告属性。如果您不需要属性,那么任何人都知道您可以简单地添加受保护的类别。 @eonil: "你也可以做 [(id)obj hiddenMethod]。"是的,您可以这样做,但如果该方法不在任何包含的接口中,您会从编译器收到警告。【参考方案5】:

可以将方法定义为父类的私有方法,在子类中可以使用[super performSelector:@selector(privateMethod)];

【讨论】:

【参考方案6】:

您可以在某种程度上对类别进行此操作。

@interface SomeClass (Protected)
-(void)doMadProtectedThings;
@end

@implementation SomeClass (Protected)

- (void)doMadProtectedThings
    NSLog(@"As long as the .h isn't imported into a class of completely different family, these methods will never be seen. You have to import this header into the subclasses of the super instance though.");


@end

如果您在另一个类中导入类别,则不会隐藏这些方法,但您只是没有。由于 Objective-C 的动态特性,实际上不可能完全隐藏方法而不管调用实例类型如何。

最好的方法可能是@Brian Westphal 回答的类延续类别,但您必须为每个子类实例重新定义该类别中的方法。

【讨论】:

【参考方案7】:

我刚刚发现了这一点,它对我有用。为了改进亚当的回答,在你的超类中实现 .m 文件中的受保护方法,但不要在 .h 文件中声明它。在您的子类中,在您的 .m 文件中创建一个新类别,并声明超类的受保护方法,您可以在子类中使用超类的受保护方法。如果在运行时强制,这最终不会阻止所谓受保护方法的调用者。

/////// SuperClass.h
@interface SuperClass

@end

/////// SuperClass.m
@implementation SuperClass
- (void) protectedMethod

@end

/////// SubClass.h
@interface SubClass : SuperClass
@end

/////// SubClass.m
@interface SubClass (Protected)
- (void) protectedMethod ;
@end

@implementation SubClass
- (void) callerOfProtectedMethod

  [self protectedMethod] ; // this will not generate warning
 
@end

【讨论】:

在这种情况下,编译器仍然会抛出有关未实现方法protectedMethod的警告 这是一个很好的解决方法,但您可以进行扩展,而不是创建一个类别(受保护)。 @skywinder 可能在早期版本中是这样,但是当前版本的Xcode对这个解决方案没有问题。【参考方案8】:

使用@protected 变量的另一种方式。

@interface SuperClass:NSObject
  @protected
    SEL protectedMehodSelector;


- (void) hackIt;
@end

@implementation SuperClass

-(id)init

self = [super init];
if(self) 
 protectedMethodSelector = @selector(baseHandling);
 

return self;


- (void) baseHandling 

  // execute your code here


-(void) hackIt 

  [self performSelector: protectedMethodSelector];


@end

@interface SubClass:SuperClass
@end

@implementation SubClass

-(id)init

self = [super init];
if(self) 
 protectedMethodSelector = @selector(customHandling);
 

return self;


- (void) customHandling 

  // execute your custom code here


@end

【讨论】:

你可以将受保护的IVars放在一个名为protected的头文件中的类扩展中【参考方案9】:

我通常用内部前缀命名受保护的方法:

-(void) internalMethod;

【讨论】:

以上是关于Objective-C 中的受保护方法的主要内容,如果未能解决你的问题,请参考以下文章

无法访问子类中的受保护方法[重复]

使用 Java 反射访问测试用例中的受保护方法

覆盖 Java 中的受保护方法

为啥只有 clone 和 finalize 是对象类中的受保护方法?

无法访问派生类中的受保护方法

超类中的受保护方法在不同包中的子类中是不是可见? [复制]