2010-03-30 6 views
5

Ich versichere, dass in Objective-C ich Instanzvariablen als Teil der Schnittstelle meiner Klasse deklarieren müssen, auch wenn diese Variablen Implementierungsdetails sind und privaten Zugriff haben.Objective-C: Wie Abstraktion Lecks zu verhindern

In "subjektiv" C, kann ich eine Variable in meiner .c-Datei deklarieren und es ist nicht sichtbar außerhalb dieser Kompilierungseinheit. Ich kann es in der entsprechenden .h-Datei deklarieren, und dann kann jeder, der in dieser Kompilierungseinheit verlinkt, die Variable sehen.

Ich frage mich, ob es eine gleichwertige Wahl in Objective-C gibt, oder ob ich tatsächlich jeden Ivar in der .h für meine Klasse erklären muss.

Ari.

+3

+1, und für Subjektive C beachten. –

Antwort

2

Ari,

Ein guter Hinweis auf wie „unsichtbar“ Instanz Variablendeklarationen erreichen kann be found here mit Kredit zu Matt Gallagher respekt gegeben.

Hoffnung, es hilft, Frank

+0

Rechts. Das Bit, das meine Frage tatsächlich beantwortet, ist, dass ich einen Teil des @ Interface in meine .m-Datei einfügen kann. Danke für den Zeiger. – iter

0

Zugang zu beschränken, können Sie die @private oder @protected Schlüsselwörter verwenden:

@interface Foo : NSObject { 
    @private 
    int barPrivate; 

    @protected 
    int barProtected; 

    @public 
    int barPublic; 
} 
@end 

EDIT:Scratch alles, stellt sich heraus, ich brauche etwas Schlaf wirklich.

+0

Das ist richtig, Sie können keine Instanzvariablen mit einer Kategorie hinzufügen. – codewarrior

+0

Ja, ich erinnerte mich daran, gleich nachdem ich die Antwort gepostet habe. –

+0

Erstellen Sie mehr als einmal Instanz mit verschiedenen Werten für 'bar' und Sie werden sehen -' bar' ist eine globale Variable. – Chuck

2

Die Instanzvariablen haben traditionell die Größe der Klasse zu bestimmen, benötigt worden. Es war immer schlecht, direkt auf die Ivars zuzugreifen, und darum geht es nicht. In der modernen Laufzeit ist dies weniger notwendig, aber auf keinen Fall ist es ein Abstraktionsleck, es sei denn, Clients verlassen sich auf die Ivars der Klasse, was unmöglich sein sollte, da Sie sie als @protected oder @private deklarieren, nicht wahr?

+0

Vielen Dank, dass Sie auf die ursprüngliche positive Absicht hingewiesen haben, die Ivars explizit zu nummerieren. Ich benutze wirklich dynamische Sprachen (Python, Lisp) so lange, ich vergesse, dass einige Sprachen die Größen zur Kompilierzeit wissen wollen. In vielerlei Hinsicht ist das Lernen von Objective C wie eine Reise in die Vergangenheit. Oder in einem Minenschacht: Ich kann all die verschiedenen Schichten von Sedimenten sehen, die sich über die gesamte Lebenszeit in der Sprache angesammelt haben. – iter

+0

@iter: Der Bedarf ist in Objective-C nicht mehr wirklich vorhanden. Die moderne Laufzeit funktioniert ähnlich wie Python, wobei Instanzvariablen alle Willy-Nilly zugewiesen werden können, ohne in einer Kopfzeile deklariert zu werden, aber die Sprache enthält immer noch die Syntax ihrer Vergangenheit. – Chuck

+0

Ich glaube, dass ich neulich darauf gestoßen bin, als ich anfing, auf intermittierende objc_msgSend_fixup-Fehler zu stoßen. Ich bin nicht 100% sicher, aber das Problem verschwand, als ich die object_setClass, die ich verwendet habe, um ein Objekt in eine benutzerdefinierte Klasse mit zusätzlichen Eigenschaften zu werfen, entfernt habe. –

0

ivars sind @protected standardmäßig (obwohl @private und @protected tun, die anderen Klassen nicht garantieren, nicht auf sie zugreifen können - können Sie jederzeit Zugriff auf ivars mit getValue:forKey:). Sie sollten niemals direkt direkt auf Ivars aus anderen Klassen zugreifen - die "Wahl" ist, ob Sie die Ivars als Eigenschaften verfügbar machen wollen (Sie müssen sich nur auf alle Klassen verlassen, die der Konvention folgen, nicht direkt auf Ivars zuzugreifen).

In der neuen Ziel-c-Laufzeit müssen Sie keine Ivars deklarieren, da sie zur Laufzeit synthetisiert werden können, aber das funktioniert leider nicht mit dem iPhone-Simulator um alle Ivars in der .h-Datei zu deklarieren.

+0

Ich sorge mich weniger darum, den Client-Code daran zu hindern, mit meinem Code etwas Seltsames zu tun, und mehr darum, dem Client-Programmierer mehr über meine Implementierung zu erzählen, als er wissen möchte. Wenn ich eine .h-Datei lese, möchte ich die "äußere" Form der Bibliothek lernen, die ich benutze. Wenn ich seine inneren Abläufe kennenlernen möchte, lese ich die .c oder .m, wie es der Fall sein mag. Ich halte diese zwei getrennt und getrennt. – iter

+1

Ich stimme zu - es ist ärgerlich, dass die Ivars in der .h-Datei sind, aber wie oben erwähnt, denke ich, dass es für den Compiler ist. – shosti