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

Objective-C 中的受保护方法等价于什么? 我想定义只有派生类可以调用/实现的方法。

【问题讨论】:

    标签: objective-c


    【解决方案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;
        

        【讨论】:

          猜你喜欢
          • 2011-06-14
          • 2010-10-30
          • 2012-06-18
          • 2020-09-09
          • 2014-04-22
          • 2020-03-31
          • 2012-11-18
          • 2016-02-19
          相关资源
          最近更新 更多