Odpowiedzi:
Nie możesz zadeklarować metody chronionej ani prywatnej. Dynamiczna natura Objective-C uniemożliwia implementację kontroli dostępu do metod. (Możesz to zrobić, mocno modyfikując kompilator lub środowisko uruchomieniowe, z poważną karą szybkości, ale z oczywistych powodów nie jest to zrobione).
Zaczerpnięte ze źródła .
Możesz zasymulować chroniony i prywatny dostęp do metod, wykonując następujące czynności:
Te zabezpieczenia nie są, jak zauważył Sachin, wymuszane w czasie wykonywania (jak na przykład w Javie).
UIGestureRecognizerSubclass.h
Oto, co zrobiłem, aby chronione metody były widoczne dla moich podklas, bez konieczności ich implementacji. Oznaczało to, że nie otrzymałem ostrzeżeń kompilatora w mojej podklasie o niekompletnej implementacji.
SuperClassProtectedMethods.h (plik protokołu):
@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end
@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end
SuperClass.m: (kompilator wymusi teraz dodanie chronionych metod)
#import "SuperClassProtectedMethods.h"
@implementation SuperClass
- (void) protectedMethod:(NSObject *)foo {}
@end
Podklasa 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.
performSelector
na nim.
[(id)obj hiddenMethod]
. Dokładnie mówiąc, metoda chroniona nie jest obsługiwana w Objective-C.
Właśnie to odkryłem i działa dla mnie. Aby ulepszyć odpowiedź Adama, w swojej superklasie zrób implementację chronionej metody w pliku .m, ale nie deklaruj jej w pliku .h. W swojej podklasie utwórz nową kategorię w swoim pliku .m z deklaracją chronionej metody nadklasy i możesz użyć chronionej metody nadklasy w swojej podklasie. Nie zapobiegnie to ostatecznie wywołującemu rzekomo chronionej metody, jeśli zostanie wymuszone w czasie wykonywania.
/////// 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
Inny sposób wykorzystania @chronionych zmiennych.
@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
Możesz zdefiniować metodę jako prywatną metodę klasy nadrzędnej i używać jej [super performSelector:@selector(privateMethod)];
w klasie potomnej.
Można rodzaj zrobić z kategorii.
@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
Metody nie są ukryte, jeśli importujesz kategorię do innej klasy, ale po prostu tego nie robisz. Ze względu na dynamiczny charakter Objective-C niemożliwe jest całkowite ukrycie metody, niezależnie od typu wywołującej instancji.
Najlepszym sposobem jest prawdopodobnie kategoria kontynuacji klasy, na którą odpowiedział @Brian Westphal, ale będziesz musiał ponownie zdefiniować metodę w tej kategorii dla każdej instancji z podklasą.
Jedną z opcji jest użycie rozszerzenia klasy do ukrycia metod.
W .h
:
@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
W .m
:
@interface SomeAppDelegate()
- (void)localMethod;
@end
@implementation SomeAppDelegate
- (void)localMethod
{
}
@end
@interface
deklaracji w pliku .m. Możesz po prostu zadeklarować funkcję i użyć jej, a będzie ona traktowana jako prywatna.