2013-10-26 14 views
6

Ich habe mit dem || = Feature Rubin als die spät und bin im Grunde in der Liebe zu lernen, wie sie faul Getter viel einfacher in Objective C. machen würdenRubin || = äquivalent in Objective-C

Derzeit schreiben ich schreibe Getter wie:

- (NSArray *)myArray { 
    if (!_myArray) { 
    _myArray = [NSArray array]; 
    } 
    return _myArray 
} 

Es sei denn, im etwas mit dem || fehlt = ich wäre in der Lage den vorherigen Code in Ruby schreiben mit:

- (NSArray *)myArray { 
    return _myArray ||= [NSArray array]; 
} 

das ist natürlich viel sauberer. Gibt es irgendetwas in der Objective-C-Sprache/Laufzeit, das Sie dazu befähigen würde?

Auch das folgende ist eine Zeile ternär für Getters, ich bin nicht sicher, ob es so effektiv ist wie die oben beschriebene bewährte Methode (erstes Snippet). Kann mir jemand sagen, wenn etwas schief Theres mit dabei:

- (NSArray *)myArray { 
    return _myArray = _myArray ? _myArray : [NSArray array]; 
} 
+0

Obwohl ich Objective C nicht kenne, möchten Sie '_myArray = [NSArray array];' in einer Klasse Konstruktor oder Initialisierungsmethode haben? Nochmals, nur ein möglicher Vorschlag von einem Typen, der Objective C nicht kennt: p – David

+1

Beachten Sie, dass alle oben genannten Punkte falsch sind, wenn Sie sich für Thread-Sicherheit interessieren. –

+1

Multithreading führt die Möglichkeit ein, dass Thread A den Setter aufrufen, den Non-Nil-Test nicht bestehen kann und dann von Thread B, der auch den Setter aufruft und den Nicht-Nil-Test nicht besteht, vorweggenommen wird. Beide Threads haben beschlossen, ein neues - separates - 'NSArray' zu erstellen und es in' _myArray' zu speichern; Heiterkeit folgt. –

Antwort

10

Der letzte Schnipsel den gleichen Effekt wie die erste hat Sie auf dem Laufenden.

Als Verbesserung, während es keine Betreiber wie ||= in Objective-C ist, können Sie den zweiten Parameter eines ternären weglassen, wenn Betreiber und

return _myArray = _myArray ?: [NSArray array]; 

tun was

genau entspricht
return _myArray = _myArray ? _myArray : [NSArray array]; 

Dies ist eine Spracherweiterung, die von modernen Versionen von gcc und clang unterstützt wird.

Bonus: Wenn Sie mehr Tastatureingaben speichern möchten, können Sie

- (NSArray *)myArray { 
    return _myArray = _myArray ?: @[]; 
} 

Als Randnotiz tun, kann das mittlere Operand Skipping auch einen gewissen Nutzen haben.

Zum Beispiel in diesem Fall

id x = [self someMethod] ? [self someMethod] : [self anotherMethod]; 

wenn someMethod zu true wertet wird es zweimal aufgerufen werden, während

id x = [self someMethod] ?: [self anotherMethod]; 

tun wird es nur einmal aufgerufen werden.

+0

Ich mag das sehr, biete eine Validierung meines Ternärs und verbessert es. Gutes Zeug. Sehr traurig, es gibt keine || = obwohl. –

+0

In der Tat, aber bedenken Sie, dass Objective-C eine viel ältere Sprache als Ruby ist. Da ich eine so dünne Schicht über dem Original C bin, stimme ich der Design-Entscheidung zu, keinen "irrelevanten" Operator in die Sprache einzuführen. –

3

Es gibt kein literales Äquivalent, außer Sie möchten hack on Clang. Der logische Operator ||, während er kurzgeschlossen ist, bewertet seine Operanden nicht. Ein Makro, das dreifach konditionalen verwenden, erhalten Sie schließen:

#define NON_NIL(o, p) ((o) ? (o) : (p)) 

- (NSMutableArray *)myArray 
{ 
    return _myArray = NON_NIL(_myArray, [NSMutableArray array]); 
} 

weil Zuordnung in C Art wirkt wie ein Ausdruck und auf den zugewiesenen Wert auswertet.

Sie könnten auch ein OR_ASSIGN() Makro machen, aber ich werde das als Übung für den völlig geistesgestörten Leser verlassen.

Vielleicht ebenso wäre deranged eine Funktion:

id lazySet(id *obj; id(^valBlock)(void)) 
{ 
    if(!(*obj)){ 
     *obj = valBlock(); 
    } 
    return *obj; 
} 

- (NSMutableArray *)myArray 
{ 
    return lazySet(&_myArray, ^{return [NSMutableArray array]}); 
} 

aber das ist einfach lächerlich zu bekommen.

+0

faszinierend, aber gruselig und irgendwie hässlich zu sehen. Jedenfalls habe ich gerade ein neues Wort gelernt: geistesgestört. Ich werde es in den nächsten Tagen sicherlich missbrauchen. Danke für den Englischunterricht. –

+0

Oh, und Sie können das erste Makro mit dem "missing-middle" 'verbessern?:" Operator –

+0

Mein Vergnügen, @Gabriele! (Danke, dass ich darauf hingewiesen habe. Ich habe eine leichte, vielleicht irrationale Vorliebe dafür, den mittleren Operanden nicht auszulassen.) –