Ist eine private synthetisierte Eigenschaft ein Oxymoron?

8

Nachdem ich ein Anfänger-iPhone-Entwicklerbuch durchgelesen und den Beispielcode online gelesen habe, ist mir aufgefallen, dass die meisten Objective-C-Programmierer fast jede Instanzvariable synthetisieren. Einige Variablen sind für Snythesize geeignet, aber die meisten sollten nicht das objektorientierte Prinzip der Kapselung berücksichtigen. Die schlimmsten sind synthetisierte Eigenschaften, die als privat markiert sind. Ein C ++ - Programmierer, der versucht, den Code einer anderen Person zu verwenden, liest die öffentlichen Felder und Methoden in der Header-Datei. Sie werden die privaten Variablen überspringen. Dieser C ++ - Programmierer weiß nicht, dass Sie die privaten Eigenschaften sinnvoll einsetzen wollten.

Werfen Sie einen Blick auf diese Beispielvorlage auf Laden des faulen Tabellenimages von Apple zur Verfügung gestellt:

Kopfzeile

%Vor%

Quelle

%Vor%

Jetzt weiß ich, dass das nicht C ++ ist und wir sollten nicht davon ausgehen, dass alle C ++ - Praktiken in Objective C berücksichtigt werden sollten. Aber Objective C sollte gute Gründe haben, von allgemeinen Programmierpraktiken abzuweichen.

  1. Warum werden alle die privaten Ivars synthetisiert? Wenn Sie das Projekt als Ganzes betrachten, wird nur NSMutableArray *workingArray von externen Klassen verwendet. Also sollte keiner der anderen Ivars Setter und Getter haben.
  2. Warum werden sehr empfindliche Ivare synthetisiert? Zum einen, da id delegate nun einen Setter hat, kann der Benutzer dieses Objekts den Delegaten in der Mitte des XML-Parsings wechseln, was nicht sinnvoll ist. Außerdem sind NSData *dataToParse unverarbeitete XML-Daten, die vom Netzwerk abgerufen werden. Jetzt, da es einen Setter hat, kann der Benutzer dieses Objekts die Daten beschädigen.
  3. Was ist der Punkt, um alles private in der Kopfzeile zu markieren? Da alle Ivars synthetisiert werden, um Getter / Setter zu haben, sind sie effektiv öffentlich. Sie können sie auf alles einstellen, was Sie wollen, und Sie können ihren Wert bekommen, wann immer Sie wollen.
JoJo 27.04.2011, 17:03
quelle

2 Antworten

10

Ich folge in vielen meiner Kurse dem Idiom, das in diesem Beispiel modelliert wurde, damit ich versuchen kann, meine eigene Rechtfertigung für diese Praxis zu erklären.

Die Eigenschaften in diesem Beispiel sind in einer Klassenerweiterung in der .m-Datei deklariert. Dies macht sie effektiv privat. Jeder Versuch, von einer anderen Klasse auf diese Eigenschaften zuzugreifen, führt beim Kompilieren zum Fehler "Eigenschaft nicht gefunden".

Für Entwickler, die aus anderen Sprachen kommen, mag es seltsam erscheinen, Getter und Setter für private Instanzvariablen zu synthetisieren. Tatsächlich gibt es nur einen Grund, warum ich das tue. Wenn sie konsistent verwendet werden, können synthetisierte Eigenschaften die Speicherverwaltung vereinfachen und helfen, unvorsichtige Fehler zu vermeiden, die zu Fehlern führen können. Hier sind ein paar Beispiele:

Bedenken Sie Folgendes:

%Vor%

dagegen:

%Vor%

Viele Entwickler würden behaupten, dass diese beiden Aufgaben funktional gleichwertig sind, aber es gibt einen wichtigen Unterschied. Die zweite Zuweisung verliert Speicher, wenn workingPropertyString bereits auf ein beibehaltenes Objekt zeigt. Um Code zu schreiben, der dem synthetisierten Setter funktionell entspricht, müssten Sie etwas wie folgt tun:

%Vor%

Dieser Code verhindert das Lecken vorhandener Objekte, auf die die Instanzvariable möglicherweise verweist, und die Möglichkeit, dass Sie der Instanzvariablen dasselbe Objekt möglicherweise erneut zuweisen. Der synthetisierte Setter macht das alles für dich.

Natürlich können wir sehen, dass (workingPropertyString != newString) in diesem Fall immer wahr ist, sodass wir diese spezielle Zuweisung vereinfachen können. Tatsächlich können Sie in den meisten Fällen wahrscheinlich mit einer einfachen direkten Zuweisung zu einer Instanzvariablen durchkommen, aber natürlich sind es die Ausnahmefälle, die dazu neigen, die meisten Fehler zu erzeugen. Ich bevorzuge es, auf Nummer sicher zu gehen und alle meine Objektinstanzvariablen durch synthetisierte Setter zu setzen. Alle meine Instanzobjektzuordnungen sind einfache Einzeiler, die wie folgt aussehen:

%Vor%

oder das:

%Vor%

Diese Einfachheit und Konsistenz gibt meinem schwachen Gehirn weniger Stoff zum Nachdenken. Als Ergebnis habe ich fast nie Fehler im Zusammenhang mit der Speicherverwaltung. (Ich bin mir bewusst, dass das autorelease idiom theoretisch übermäßig viel Speicher in einer engen Schleife verbrauchen könnte, aber ich habe dieses Problem in der Praxis noch nicht gesehen. Wenn ich es jemals tue, ist es ein einfacher Fall zu optimieren.)

Eine andere Sache, die ich an dieser Übung mag, ist, dass meine Dealloc-Methoden alle so aussehen:

%Vor%

EDIT: Daniel Dickison wies auf etwas hin Risiken für die Verwendung von Accessoren in Dealloc das hatte ich nicht bedacht. Siehe die Kommentare.

wobei jede Objekteigenschaft einfach auf Null gesetzt wird. Dadurch wird gleichzeitig jede beibehaltene Eigenschaft freigegeben, während sie auf Null gesetzt wird, um bestimmte Abstürze aufgrund von EXC_BAD_ACCESS zu vermeiden.

Beachten Sie, dass ich self.delegate = nil; festgelegt habe, obwohl diese Eigenschaft als (nonatomic, assign) deklariert wurde. Diese Zuordnung war nicht unbedingt notwendig. Tatsächlich könnte ich die Eigenschaften für meine (nonatomic, assign) -Objekte insgesamt abschaffen, aber ich habe wieder gefunden, dass die konsequente Anwendung dieses Idioms auf alle meine Instanzvariablen mein Gehirn weniger zum Nachdenken anregt und die Wahrscheinlichkeit, dass ich es werde, weiter reduziert Erstellen Sie einen Fehler durch einen unvorsichtigen Fehler. Bei Bedarf kann ich einfach eine Eigenschaft von (nonatomic, assign) nach (nonatomic, retain) umdrehen, ohne einen Speicherverwaltungscode zu berühren. Ich mag das.

Man könnte Konsistenz auch als Argument für die Synthese von Eigenschaften für private Skalarvariablen verwenden, wie das Beispiel von BOOL storingCharacterData; gezeigt hat. Diese Vorgehensweise stellt sicher, dass jede Zuweisung von Instanzvariablen wie self.foo = bar; aussieht. Normalerweise mache ich mir keine Mühe, private Skalareigenschaften zu erstellen, aber ich kann eine gewisse Berechtigung für diese Praxis sehen.

    
cduhn 27.04.2011, 19:20
quelle
0
  

Warum sind all die privaten Ivars?   synthetisiert? Wenn du dir das anschaust   Projekt als Ganzes nur   NSMutableArray * workingArray wird verwendet   durch äußere Klassen. Also nichts von dem   andere Ivars sollten Setter haben und   Getters.

Kein wirkliches Bedürfnis; Wenn Sie trotzdem direkt auf alle Ivars zugreifen möchten, brauchen Sie @synthesize nicht.

  

Warum sind sehr empfindliche Ivars   synthetisiert? Zum einen, jetzt diese ID   Delegat hat einen Setter, der Benutzer von   Dieses Objekt kann den Delegaten wechseln   Mitte des XML-Parsing, etwas   das macht keinen Sinn. Auch, NSData   * dataToParse sind unverarbeitete XML-Daten, die aus dem Netzwerk abgerufen werden. Jetzt, wo es eine hat   Setter, der Benutzer dieses Objekts kann   korrumpieren die Daten.

Keiner der Setter / Getter wurde öffentlich deklariert. Wenn ein Client der Klasse Dinge korrumpieren möchte, indem er den Delegaten in der Mitte wechselt, müssen sie die Kapselung unterbrechen, um dies zu tun.

Also, letztendlich, ein Nicht-Problem.

  

Was ist der Punkt, alles zu markieren?   privat im Header? Seit alle Ivars   Sind synthetisiert zu haben   Getters / Setter, sie sind effektiv   Öffentlichkeit. Sie können sie auf alles einstellen   Sie wollen und Sie können ihren Wert bekommen   wann immer du willst.

Beachten Sie, dass es nicht notwendig ist, die Ivars in diesem Beispiel zu deklarieren; Der Compiler wird sie automatisch basierend auf der @ Property-Deklaration synthetisieren.

Traditionell ist @private gegen jemanden geschützt, der den ivar direkt von extern zu einer Instanz der Klasse führt.

Beachten Sie, dass einInstance- & gt; ivar oder self & gt; ivar fast nie verwendet wird (und wenn es verwendet wird, ist es fast immer aus dem falschen Grund). Es gibt Verwendungen dafür, aber es ist selten.

    
bbum 27.04.2011 17:29
quelle