Risposte:
Non è possibile dichiarare un metodo protetto o privato. La natura dinamica di Objective-C rende impossibile implementare i controlli di accesso per i metodi. (Puoi farlo modificando pesantemente il compilatore o il runtime, con una grave penalità di velocità, ma per ovvie ragioni questo non viene fatto.)
Tratto dalla fonte .
È possibile simulare l'accesso protetto e privato ai metodi procedendo come segue:
Queste protezioni non sono, come ha notato Sachin, applicate in fase di esecuzione (come lo sono in Java, per esempio).
UIGestureRecognizerSubclass.h
Ecco cosa ho fatto per rendere visibili i metodi protetti alle mie sottoclassi, senza richiedere loro di implementare i metodi stessi. Ciò significava che non ricevevo avvisi del compilatore nella mia sottoclasse sull'avere un'implementazione incompleta.
SuperClassProtectedMethods.h (file di protocollo):
@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end
@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end
SuperClass.m: (il compilatore ora ti costringerà ad aggiungere metodi protetti)
#import "SuperClassProtectedMethods.h"
@implementation SuperClass
- (void) protectedMethod:(NSObject *)foo {}
@end
SubClass.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.
performSelectorfarlo.
[(id)obj hiddenMethod]. Precisamente, il metodo protetto non è supportato in Objective-C.
L'ho appena scoperto e per me funziona. Per migliorare la risposta di Adam, nella tua superclasse fai un'implementazione del metodo protetto nel file .m ma non dichiararlo nel file .h. Nella tua sottoclasse crea una nuova categoria nel tuo file .m con la dichiarazione del metodo protetto della superclasse e puoi usare il metodo protetto della superclasse nella tua sottoclasse. Questo alla fine non impedirà il chiamante del metodo presumibilmente protetto se forzato in fase di esecuzione.
/////// 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
Un altro modo per utilizzare le variabili @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
È possibile definire il metodo come metodo privato della classe genitore e utilizzarlo [super performSelector:@selector(privateMethod)];nella classe figlia.
Si può sorta di farlo con una categoria.
@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
I metodi non vengono nascosti se importi la categoria in un'altra classe, ma semplicemente non lo fai. A causa della natura dinamica di Objective-C è effettivamente impossibile nascondere completamente un metodo indipendentemente dal tipo di istanza chiamante.
Il modo migliore per procedere è probabilmente la categoria di continuazione della classe a cui ha risposto @Brian Westphal, ma dovrai ridefinire il metodo in questa categoria per ogni istanza sottoclasse.
Un'opzione è usare l' estensione di classe per nascondere i metodi.
In .h:
@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
In .m:
@interface SomeAppDelegate()
- (void)localMethod;
@end
@implementation SomeAppDelegate
- (void)localMethod
{
}
@end
@interfacedichiarazione nel file .m. Puoi semplicemente dichiarare una funzione e usarla e tratterà come privata.