Expose a private Objective-C method or property to subclasses

后端 未结 7 1246
栀梦
栀梦 2020-12-05 06:43

According to some official talk, a class in Objective-C should only expose public methods and properties in its header:

@interface MyClass : NSObject

@prope         


        
相关标签:
7条回答
  • 2020-12-05 07:06

    Your only choice is to declare it as public in the header file. If you want to at least keep some method separation, you can create a category and have all your protected methods and attributes there, but in the end everything will still be public.

    #import "MyClass.h"
    
    @interface MyClass (Protected)
    
    - (void) protectedMethods;
    
    @end
    
    0 讨论(0)
  • 2020-12-05 07:17

    Simply create a .h file with your class extension. Import this into your .m files. Incidentally, this is a great way to test private members without breaking encapsulation (I'm not saying you should test private methods :) ).

    // MyClassProtectedMembers.h
    @interface MyClass()
    
    @property (nonatomic, strong) MyPrivateObject *privateObject;
    - (void) privateMethod;
    @end
    

    /////////////////

    #import "MyClassProtectedMembers.h"
    
    @implementation MyClass
    // implement privateMethod here and any setters or getters with computed values
    @end
    

    Here's a gist of the idea: https://gist.github.com/philosopherdog/6461536b99ef73a5c32a

    0 讨论(0)
  • 2020-12-05 07:19

    I see good answers for making properties visible, but I don't see exposing the methods addressed very clearly in any of these answers. Here is how I have successfully exposed private methods to the subclass using a Category:

    SomeSuperClass.m:

    @implementation SomeSuperClass
    
    -(void)somePrivateMethod:(NSString*)someArgument {
        ...
    }
    

    SomeChildClass.h

    @interface SomeChildClass : SomeSuperClass
    

    SomeChildClass.m

    @interface SomeSuperClass (exposePrivateMethod)
    -(void)somePrivateMethod:(NSString*)someArgument;
    @end
    
    @implementation SomeChildClass
    
    -(void)doSomething {
        [super somePrivateMethod:@"argument"];
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-05 07:22

    While the other answers are correct, I'd like to add...

    Private, protected and public are available for instance variables as such:

    @interface MyClass : NSObject {
    @private
      int varA;
    
    @protected
      int varB;
    
    @public
      int varC;
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-05 07:23

    That's because there's not even a real distinction between private and public. While the compiler may warn you about an interface missing a certain method or instance variable, your program will still work.

    0 讨论(0)
  • 2020-12-05 07:24

    One way to solve this is to re-declare the property in your subclass's class extension, and then add an @dynamic statement so that the compiler won't create an overriding implementation of that property. So something like:

    @interface SuperClass ()
    
    @property (nonatomic, strong) id someProperty;
    
    @end
    
    ....
    
    
    @interface SubClass ()
    
    @property (nonatomic, strong) id someProperty;
    
    @end
    
    @implementation SubClass
    
    @dynamic someProperty;
    
    @end
    

    This obviously isn't ideal because it duplicates a privately visible declaration. But it is quite convenient and helpful in some situations so I'd say evaluate on a case-by-case basis the dangers involved in this duplication vs. exposing the property in the public interface.

    An alternative - that is used by Apple in UIGestureRecognizer - is to declare the property in a separate category header file explicitly named as "private" or "protected" e.g. "SomeClass+Protected.h". That way, other programmers will know they ought not import the file. But, if you don't control the code you're inheriting from, that's not an option.

    0 讨论(0)
提交回复
热议问题