Frage

Als Objective-C-Neuling (aber langjähriger C/++-Programmierer) suche ich nach Ratschlägen/Empfehlungen zu Namenskonventionen für Variablen.

Mein persönlicher Vorzug wäre die Verwendung eines Präfixes für Beispielvariablen, sowohl aus Gründen der Klarheit innerhalb von Funktionen als auch zur Verhinderung einer Verschattung von Funktionsparametern.Allerdings bin ich ein Fan von Eigenschaften, die Präfixe ausschließen (es sei denn, Sie setzen Ihren Eigenschaftsnamen auch Präfixe voran, was nicht so gut funktioniert und albern aussieht).Ebenso könnte ich die „self.variable“-Konvention verwenden, aber nur, wenn ich ALLES zu einer Eigenschaft mache.

Welchen Namensstil bevorzugen Sie angesichts des folgenden Codes für Instanz-/Funktionsvariablen?Und wenn Sie sich nicht die Mühe machen, wie gehen Sie mit der Beschattung von Funktionsparametern um?

@interface GridItem : NSObject
{
    CGRect _rect;
    ...  
}
@end

-(void) initFromRect:(CGRect)rect
{
    _rect = rect;
    ...
}

Prost!

War es hilfreich?

Lösung

Die meisten Cocoa-Projekte verwenden Underbar als Nicht-IBOutlet Instanzvariablenpräfix und verwenden Sie kein Präfix für IBOutlet Instanzvariablen.

Der Grund, warum ich keine Unterstriche verwende IBOutlet Instanzvariablen bedeuten, dass beim Laden einer NIB-Datei dieser Setter aufgerufen wird, wenn Sie über eine Setter-Methode für einen angeschlossenen Ausgang verfügen. Jedoch Dieser Mechanismus funktioniert nicht Verwenden Sie die Schlüsselwertcodierung, also ein IBOutlet, dessen Name mit einem Unterstrich vorangestellt ist (z.B. _myField) Wille nicht festgelegt werden, es sei denn, der Einrichter wird genauso benannt wie die Steckdose (z.B. set_myField:), was nicht standardisiert und eklig ist.

Beachten Sie außerdem, dass die Verwendung von Eigenschaften wie self.myProp Ist nicht das Gleiche wie der Zugriff auf Instanzvariablen.Du bist eine Nachricht senden wenn Sie eine Eigenschaft verwenden, genau wie wenn Sie die Klammernotation verwenden würden [self myProp].Eigenschaften bieten Ihnen lediglich eine prägnante Syntax für die Angabe von Getter und Setter in einer einzigen Zeile und ermöglichen Ihnen, deren Implementierung zu synthetisieren.Sie schließen den Nachrichtenversandmechanismus nicht wirklich kurz.Wenn Sie direkt auf eine Instanzvariable zugreifen möchten, dieser aber das Präfix voranstellen möchten self Du musst behandeln self als Hinweis, so self->myProp Das ist wirklich ein Feldzugriff im C-Stil.

Schließlich sollten Sie beim Schreiben von Cocoa-Code niemals die ungarische Notation verwenden und sich von anderen Präfixen wie „f“ und „m_“ fernhalten – diese würden den Code als von jemandem geschrieben kennzeichnen, der ihn nicht „versteht“, und dazu führen, dass er es tut von anderen Cocoa-Entwicklern mit Argwohn betrachtet werden.

Befolgen Sie im Allgemeinen die Ratschläge in der Codierungsrichtlinien für Kakao Dokument am Apple-Entwicklerverbindung, und andere Entwickler können Ihren Code aufgreifen und verstehen, und Ihr Code funktioniert gut mit allen Cocoa-Funktionen, die Laufzeit-Introspektion verwenden.

So könnte eine Fenster-Controller-Klasse nach meinen Konventionen aussehen:

// EmployeeWindowController.h
#import <AppKit/NSWindowController.h>

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    IBOutlet NSTextField *nameField;
    IBOutlet NSTextField *titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;

@end

// EmployeeWindowController.m
#import "EmployeeWindowController.h"

@implementation EmployeeWindowController

@synthesize employee = _employee;

- (id)initWithEmployee:(Employee *)employee {
    if (self = [super initWithWindowNibName:@"Employee"]) {
        _employee = [employee retain];
    }
    return self;
}

- (void)dealloc {
    [_employee release];

    [super dealloc];
}

- (void)windowDidLoad {
    // populates the window's controls, not necessary if using bindings
    [nameField setStringValue:self.employee.name];
    [titleField setStringValue:self.employee.title];
}

@end

Sie werden sehen, dass ich die Instanzvariable verwende, die auf eine verweist Employee direkt in meinem -init Und -dealloc Methode, während ich die Eigenschaft in anderen Methoden verwende.Das ist im Allgemeinen ein gutes Muster mit Eigenschaften:Berühren Sie in Initialisierern immer nur die zugrunde liegende Instanzvariable für eine Eigenschaft -dealloc, und im Getter und Setter für die Eigenschaft.

Andere Tipps

Ich folge Chris Hansons Rat hinsichtlich des Unterstrich-IVAR-Präfixes, obwohl ich zugebe, dass ich Unterstriche auch für IBOutlets verwende.Allerdings habe ich vor Kurzem mit dem Umzug begonnen IBOutlet Erklärungen an die @property Linie, gem @mmalcs Vorschlag.Der Vorteil ist, dass alle meine Ivars jetzt einen Unterstrich haben und Standard-KVC-Setter aufgerufen werden (d. h. setNameField:).Außerdem haben die Outlet-Namen im Interface Builder keine Unterstriche.

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    NSTextField *_nameField;
    NSTextField *_titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;
@property(nonatomic, retain) IBOutlet NSTextField *nameField;
@property(nonatomic, retain) IBOutlet NSTextField *titleField;

@end

Sie können das Unterstrich-Präfix für Ihre Ivars verwenden und dennoch den Nicht-Unterstrich-Namen für Ihre Eigenschaften verwenden.Für synthetisierte Accessoren gehen Sie einfach wie folgt vor:

@synthesize foo = _foo;

Dies weist den Compiler an, die foo-Eigenschaft mithilfe des ivar_foo zu synthetisieren.

Wenn Sie Ihre eigenen Accessoren schreiben, verwenden Sie einfach den Underbar-IVAR in Ihrer Implementierung und behalten den Methodennamen ohne Underbar bei.

Persönlich halte ich mich an die Namenskonventionen von Cocoa und verwende die Kamel-Schreibweise für Funktionen und Variablen sowie die Groß-/Kamel-Schreibweise für Objektnamen (natürlich ohne das führende NS).

Ich finde, dass Typpräfixe den Code für jeden undurchsichtiger machen, der ihn nicht geschrieben hat (da jeder ausnahmslos unterschiedliche Präfixe verwendet), und in einer modernen IDE ist es nicht wirklich schwierig, den Typ von etwas herauszufinden.

Mit der Einführung von Eigenschaften sehe ich keine Notwendigkeit, Klasseninstanzvariablen ein „_“ voranzustellen.Sie können eine einfache Regel festlegen (in Ihrer Header-Datei beschrieben), dass auf alle Variablen, auf die außerhalb der Klasse zugegriffen werden soll, über die Eigenschaft zugegriffen werden muss oder indem Sie benutzerdefinierte Methoden für die Klasse verwenden, um Werte zu beeinflussen.Das scheint mir viel sauberer zu sein, als Namen mit einem „_“ auf der Vorderseite zu haben.Außerdem werden die Werte ordnungsgemäß gekapselt, sodass Sie steuern können, wie sie geändert werden.

Ich verwende nicht gerne Unterstriche als Präfixe für Bezeichner, da sowohl C als auch C++ bestimmte Unterstrich-Präfixe für die Verwendung durch die Implementierung reservieren.

Ich finde die Verwendung von „self.variable“ hässlich.

Im Allgemeinen verwende ich schlichte Bezeichner (also keine Präfixe oder Suffixe) für Instanzvariablen.Wenn Ihre Klasse so kompliziert ist, dass Sie sich die Instanzvariablen nicht merken können, sind Sie in Schwierigkeiten.Für Ihr Beispiel würde ich also „rect“ als Namen der Instanzvariablen und „newRect“ oder „aRect“ als Parameternamen verwenden.

Andreas:Es gibt tatsächlich viele Cocoa-Entwickler, die überhaupt keine Präfixe für Instanzvariablen verwenden.Es ist auch in der Smalltalk-Welt äußerst verbreitet (tatsächlich würde ich sagen, dass es in Smalltalk nahezu unbekannt ist, Präfixe für Instanzvariablen zu verwenden).

Präfixe für Instanzvariablen kamen mir immer als ein C++-Ismus vor, der auf Java und dann auf C# übertragen wurde.Da die Objective-C-Welt weitgehend parallel zur C++-Welt verlief, wo die Java- und C#-Welten Nachfolger sind, würde dies den „kulturellen“ Unterschied erklären, den Sie hier zwischen den verschiedenen Entwicklergruppen erkennen könnten.

Mein Stil ist hybrid und eigentlich ein Überbleibsel aus der PowerPlant-Zeit:

Die nützlichsten Präfixe, die ich verwende, sind „in“ und „out“ für Funktions-/Methodenparameter.Dies hilft Ihnen, auf einen Blick zu erkennen, wozu die Parameter dienen, und trägt wirklich dazu bei, Konflikte zwischen Methodenparametern und Instanzvariablen zu vermeiden (wie oft haben Sie schon gesehen, dass der Parameter „Tabelle“ mit einer Instanzvariablen mit demselben Namen in Konflikt steht).Z.B.:

- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;

Dann verwende ich den bloßen Namen für Instanzvariablen und Eigenschaftsnamen:

Dann verwende ich „the“ als Präfix für lokale Variablen:theTable, theURL usw.Auch dies hilft bei der Unterscheidung zwischen lokalen Variablen und Instanzvariablen.

Dann verwende ich im PowerPlant-Stil eine Handvoll anderer Präfixe:k für Konstanten, E für Aufzählungen, g für Globale und s für Statik.

Ich benutze diesen Stil jetzt seit etwa 12 Jahren.

Obwohl ich es liebe, den Unterstrich als Präfix für Ivars zu verwenden, verabscheue ich das Schreiben @synthesize Zeilen wegen all der Duplizierung (es ist nicht sehr TROCKEN).Ich habe ein Makro erstellt, um dies zu erleichtern und die Codeduplizierung zu reduzieren.Also statt:

@synthesize employee = _employee;

Ich schreibe das:

ddsynthesize(employee);

Es handelt sich um ein einfaches Makro, das durch Token-Einfügen einen Unterstrich auf der rechten Seite hinzufügt:

#define ddsynthesize(_X_) @synthesize _X_ = _##_X_

Der einzige Nachteil besteht darin, dass es das Refactoring-Tool von Xcode verwirrt und nicht umbenannt wird, wenn Sie die Eigenschaft durch Refactoring umbenennen.

Lesen Sie neben dem, was hier gesagt wurde, unbedingt auch die Cocoa-Dokumentation zur Key Value Observing-konformen Benennung.Die strikte Befolgung dieses Musters wird Ihnen auf lange Sicht sehr helfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top