2013-10-31 6 views
5

man oft liest, dass unveränderliche Klassen copyWithZone sehr effizient in der folgenden Art und Weise implementieren können:Gibt [read] in copyWithZone für unveränderliche Klassen mit veränderbaren Unterklassen zurück wirklich sicher/eine gute Idee?

- (id) copyWithZone:(NSZone*)zone 
{ 
    return [self retain]; 
} 

Die Idee hinter dieser Implementierung ist offensichtlich: Das Original und die Kopie sind beide unveränderlich Instanzen und sie werden immer genau haben den gleichen Inhalt, also warum nicht beide auf den gleichen Speicher verweisen, indem Sie das Original beibehalten und den Aufwand des Kopierens vermeiden.

Was passiert jedoch, wenn es eine veränderbare Unterklasse gibt? Mit einer sauberen Architektur, wo eine Unterklasse nicht über Details der Implementierung ihrer Basisklasse muss kümmern, sollte die veränderbare Unterklasse in Ordnung sein copyWithZone auf diese Weise zu implementieren:

- (id) copyWithZone:(NSZone*)zone 
{ 
    MyClass* myCopy = [super copyWithZone:zone]; 
    myCopy->myMember = [myMember copyWithZone:zone]; 
    return myCopy; 
} 

Aber was bedeutet das mit der oben Superklassenimplementierung von copyWithZone? Die Unterklasse ist änderbar, also obwohl die Kopie immer noch unveränderlich ist, ist das Original jetzt änderbar, aber die Unterklasse copyWithZone dank der Superklassenimplementierung arbeitet auf einer beibehaltenen Instanz von sich selbst: self und myCopy verweisen beide auf dieselbe Instanz, also wenn ich ändere später den Wert von mutableOriginal.myMember, dann ändert sich auch immutableCopy.myMember, was einfach falsch ist.

Also sollten nicht unveränderliche Klassen copyWithZone auf folgende Weise besser implementieren?

- (id) copyWithZone:(NSZone*)zone 
{ 
    if([[self class] isMemberOfClass:[MyBaseClass class]]) 
     return [self retain]; 
    else 
    { 
     MyBaseClass* myCopy = [[self alloc] init]; 
     myCopy->myBaseMember = [myBaseMember copyWithZone:zone]; 
     return myCopy; 
    } 
} 
+2

Nicht ganz. Ich denke nicht, dass man "kopieren" nach einem der aufgeführten Ansätze implementieren sollte. Kopieren ist * sehr * intrinsisch. Sie rufen besser nicht '[Supercopy]' auf, sondern weisen bei Bedarf eine saubere, neue Instanz zu. –

Antwort

3

Ihre beste Möglichkeit wäre, ein initWithMyImmutableObject initialiser in Ihrem unveränderlichen Super haben. Ihre Unterklasse kann dann implementieren nur NSCopying mit

- (id) copyWithZone:(NSZone*)zone { 
    return [[[self superclass] alloc] initWithMyImmutableObject:self] 
} 

auf diese Weise die tatsächliche Kopieren von Eigenschaften in einem Verfahren der Superklasse durchgeführt wird, die den Zugriff auf alle privaten Mitgliedern, die kopiert werden müssen.

Verwandte Themen