2010-11-24 8 views

Antwort

15

Technisch, nein. Eigenschaften sind wirklich nur Methoden und alle Methoden sind öffentlich. Die Art, wie wir Methoden in Objective-C "schützen", besteht darin, andere nicht über sie zu informieren.

Praktisch, ja. Sie können die Eigenschaften in einer Klassenerweiterung definieren und immer noch @synthesize sie in Ihrem Hauptimplementierungsblock.

+1

Um "geschützt" zu sein, müsste die Klassenerweiterungsschnittstelle in einer separaten Header-Datei sein, um in die Klasse und ihre Unterklassen aufgenommen zu werden. – JeremyP

+0

Soweit ich das beurteilen kann, sind alle Eigenschaften, die in der Schnittstellenerweiterung der Basisklassen deklariert sind, für Unterklassen nicht verfügbar - sie sind beschränkt auf private, nicht geschützte Bereiche. Siehe diese SO-Diskussion: http://stackoverflow.com/questions/5588799/objective-c-how-do-you-access-parent-properties-from-subclasses – memmons

+0

@Harkonian wenn Sie den Selektor selbst erklären, können Sie immer anrufen es. Es gibt keine Möglichkeit, eine Methode zu "schützen", außer einfach ihre Deklaration zu verbergen. Objective-C hat nicht das Konzept geschützter oder privater Methoden. Nur geschützte oder private Ivars. –

0

Sie könnten diese Syntax in der Unterklassenimplementierung verwenden.

@interface SuperClass (Internal) 

@property (retain, nonatomic) NSString *protectedString; 

@end 
+1

Können Sie eine kurze Erklärung hinzufügen, wie diese Lösung funktioniert? – HairOfTheDog

9

Dies ist möglich durch eine Klassenerweiterung (nicht Kategorie), die Sie in den Implementierungsdateien sowohl die Basisklasse und Unterklassen umfassen.

Eine Klasse-Erweiterung wird zu einer Kategorie ähnlich definiert, aber ohne die Kategorienamen:

@interface MyClass() 

In einer Klasse-Erweiterung können Sie Eigenschaften erklären, die in der Lage sein werden, die Träger ivars (XCode> 4.4 zu synthetisieren automatische Synthese der Ivars funktioniert auch hier).

In der Erweiterungsklasse können Sie Eigenschaften überschreiben/ändern (readonly in readwrite ändern usw.) und Eigenschaften und Methoden hinzufügen, die für die Implementierungsdateien "sichtbar" sind (beachten Sie jedoch, dass die Eigenschaften und Methoden dies nicht sind) wirklich privat und kann immer noch von Selektor aufgerufen werden).

Andere haben mit einer separaten Header-Datei MyClass_protected.h hierfür vorgeschlagen, aber dies kann auch in der Haupt-Header-Datei wie folgt mit #ifdef erfolgen:

Beispiel:

BaseClass.h

@interface BaseClass : NSObject 

// foo is readonly for consumers of the class 
@property (nonatomic, readonly) NSString *foo; 

@end 


#ifdef BaseClass_protected 

// this is the class extension, where you define 
// the "protected" properties and methods of the class 

@interface BaseClass() 

// foo is now readwrite 
@property (nonatomic, readwrite) NSString *foo; 

// bar is visible to implementation of subclasses 
@property (nonatomic, readwrite) int bar; 

-(void)baz; 

@end 

#endif 

BaseClass.m

// this will import BaseClass.h 
// with BaseClass_protected defined, 
// so it will also get the protected class extension 

#define BaseClass_protected 
#import "BaseClass.h" 

@implementation BaseClass 

-(void)baz { 
    self.foo = @"test"; 
    self.bar = 123; 
} 

@end 

ChildClass.h

// this will import BaseClass.h without the class extension 

#import "BaseClass.h" 

@interface ChildClass : BaseClass 

-(void)test; 

@end 

ChildClass.m

// this will implicitly import BaseClass.h from ChildClass.h, 
// with BaseClass_protected defined, 
// so it will also get the protected class extension 

#define BaseClass_protected 
#import "ChildClass.h" 

@implementation ChildClass 

-(void)test { 
    self.foo = @"test"; 
    self.bar = 123; 

    [self baz]; 
} 

@end 

Wenn Sie #import nennen, ist es im Grunde kopieren Pasten die .h-Datei, wo Sie es importieren. Wenn Sie ein #ifdef haben, wird es nur den Code enthalten, wenn der #define mit diesem Namen festgelegt ist.

In Ihrer .h-Datei legen Sie nicht die Definition fest, sodass Klassen, die diese .h importieren, die Erweiterung der geschützten Klasse nicht sehen. In der Basisklasse und der Unterklasse .m-Datei verwenden Sie #define, bevor Sie #import verwenden, damit der Compiler die geschützte Klassenerweiterung enthält.