2010-11-22 13 views
4

Ist es möglich, den erlaubten Typ eines Ivar in einer Unterklasse einzuschränken? Etwas wie folgt aus:Ziel C - Narrow-Instanz Variablentypen in Unterklassen?

@interface person: NSObject { 
    NSArray *friendArray; 
} 

@interface mutablePerson: person { 
    NSMutableArray *friendArray; 
} 

Ich habe gerade versucht, dass genaue Code, und Xcode gab mir einen Compiler-Fehler. Ich frage mich, ob es einen Weg gibt.

Das Projekt, an dem ich arbeite, wird eine Menge dieser Situation haben. Ich verstehe, dass ich Casts verwenden kann, um den Code arbeiten zu lassen. Aber wenn ich das mache, werde ich sehr viele Zauber machen, und ich frage mich, ob es einen besseren Weg gibt.

+1

1) nicht erlaubt ist Narrowing , aber Sie haben es erweitert, was ist. 2) Sie deklarieren den gleichen Mitgliedsnamen erneut - das geht nicht. Gib ihm einen neuen Namen und ändere die Accessoren. –

+0

haben Sie das NSMutableCopying-Protokoll getestet/implementiert? wahrscheinlich ist was du willst. – nacho4d

+0

@Alex Braun. Es hat sich eingeengt. 'NSMutableArray' ist eine Unterklasse von' NSArray'. –

Antwort

0

I beendete die setter zwingende zu behaupten, daß das Objekt festgelegt wird, der geeigneten Typ ist, und eine neue Nur-Lese-Getter zu schaffen, wie folgt aus:

@interface MutablePerson { 
} 

@property (readonly) NSMutableArray *mutableFriendArray; 

@implementation MutablePerson 

-(NSMutableArray *) mutableFriendArray { 
    NSMutableArray *ret = (NSMutableArray *)[super friendArray]; 
    NSAssert ([ret isKindOfClass: [NSMutableArray class]], @"array should be mutable"); 
    return ret; 
} 

-(void) setFriendArray: (NSMutableArray *) array { 
    NSAssert ([array isKindOfClass: [NSMutableArray class]], @"array should be mutable"); 
    [super setFriendArray: array]; 
} 
0

@klasse macht überhaupt keinen Sinn ... es sollte @interface sein. Der erste Fehler ist also rein syntaktisch.

Und nein, Sie können den Typ eines Ivar nicht ändern. Und das aus einem guten Grund: Das Einschränken (wie Sie es tun) kann nicht funktionieren, weil die Elternklasse möglicherweise auf eine andere Implementierung angewiesen ist. . Erweiternden kann es nicht so gut (vor allem für den analogen Grund

+0

Danke, habe den Code hier korrigiert; Es war korrekt, als ich es in Xcode versuchte. –

0

Wenn der Compiler sagt ‚nein‘, dann ist das Ihre Antwort würde ich Accessoren benutzen.

//Person 
-(NSArray *)friends; 


//MutablePerson 
-(void)addFriend:(person *)friend; 

In der MutablePerson Sie könnte eine andere erklären Array friends zu speichern oder Sie können die ivar direkt in addFriend: zugreifen:..

-(void)addFriend:(person *)friend 
{ 
    _friendsArray = [_friendsArray arrayByAddingObject: friend]; 
}  

Zugriff ivars direkt nicht klug ist, würde ich Ihre Klasse Design überdenken, was der Grund ist ein veränderliches für und mit unveränderliche Versionen der Person?

1

Nein, Sie können keine Ivars neu deklarieren. Sie können jedoch eine neue methodenbasierte Eigenschaft erstellen, ohne einen neuen ivar zu erstellen.

@property (nonatomic, copy) NSMutableArray* mutableFriends; 

@implementation MutablePerson 

- (NSMutableArray*)mutableFriends { 
    return (NSMutableArray*)friendArray; 
} 

- (void)setMutableFriends:(NSMutableArray*)friends { 
    self.friendsArray = [friends mutableCopy]; 
} 

@end