Ich erstelle einen Reddit-Client für Lernzwecke. Ich brauche eine Datei mit Konstanten. Ich habe darüber nachgedacht, die Datei in die Reddit-Prefix.pch
Datei zu importieren , um die Konstanten für alle Dateien verfügbar zu machen. Ist es eine gute Art, Dinge zu tun? Außerdem habe ich meine Recherchen durchgeführt und verschiedene Methoden zum Erstellen von Konstanten gefunden, aber ich weiß nicht, welche ich verwenden soll:
#define
Makroconst
static const
extern const
enum
Welcher Weg ist der bevorzugte Weg? Was ist die Konvention? Ich weiß, dass "es darauf ankommt", aber meine Frage lautet genauer: Was sind die Anwendungsfälle für jede dieser Lösungen?
extern const
Muss ich bei Verwendung die Datei importieren, sonst sind die Konstanten global verfügbar, ohne die Datei zu importieren?
Eine Sache, die ich logischerweise schließen könnte, ist, dass dies enum
die beste Wahl ist, wenn Sie so etwas wie benutzerdefinierte Fehlerdomänen definieren (habe ich tatsächlich Recht?). Aber was ist mit den anderen?
quelle
enum
ist nur für ganzzahlige Werte nützlich.#define
und Konstanten können ein beliebiger Datentyp sein.const
,,static const
undextern const
sind bis auf den Umfang alle gleich. Es gibt also wirklich nur drei Möglichkeiten.Antworten:
Die erste Frage ist, welchen Umfang Ihre Konstanten haben sollen. Das sind eigentlich zwei Fragen:
Wenn sie spezifisch und intern für eine einzelne Klasse sind, deklarieren Sie sie wie
static const
oben in der .m-Datei wie folgt:Wenn sie sich auf eine einzelne Klasse beziehen, aber öffentlich sein / von anderen Klassen verwendet werden sollen, deklarieren Sie sie wie
extern
im Header und definieren Sie sie in der .m:Wenn sie global sein sollen, deklarieren Sie sie in einem Header und definieren Sie sie in einem entsprechenden Modul, speziell für diese Konstanten.
Sie können diese für verschiedene Konstanten mit unterschiedlichen Ebenen, wie global sie sein sollen, und für verschiedene globale Konstanten, die einfach nicht zusammengehören, mischen und abgleichen. Wenn Sie möchten, können Sie sie in separate Module mit jeweils einem eigenen Header einfügen wollen.
Warum nicht
#define
?Die alte Antwort lautet: "Makros haben keine Typinformationen", aber Compiler sind heutzutage ziemlich schlau darin, alle Typprüfungen auf Literale (auf die Makros erweitert werden) und Variablen durchzuführen.
Die moderne Antwort ist, dass der Debugger nichts über Ihre Makros weiß. Sie können
[myThing addObserver:self forKey:MyThingNotificationKey]
in einem Debugger-Befehl nicht sagen, obMyThingNotificationKey
es sich um ein Makro handelt. Der Debugger kann nur wissen, ob es sich um eine Variable handelt.Warum nicht
enum
?Nun, rmaddy hat mich in den Kommentaren geschlagen:
enum
Kann nur ganzzahlige Konstanten definieren. Dinge wie Seriennummern, Bitmasken, Vier-Byte-Codes usw.Für diese Zwecke
enum
ist großartig und Sie sollten es unbedingt verwenden. (Noch besser ist , verwenden Sie dieNS_ENUM
undNS_OPTIONS
Makros .) Für andere Dinge, Sie müssen etwas anderes nutzen;enum
macht nichts anderes als ganze Zahlen.Und andere Fragen
Wahrscheinlich harmlos, aber wahrscheinlich übertrieben. Importieren Sie Ihre Konstanten-Header dort, wo Sie sie benötigen.
#define
: Ziemlich begrenzt. Ich bin mir ehrlich gesagt nicht sicher, ob es einen guten Grund mehr gibt, dies für Konstanten zu verwenden.const
: Am besten für lokale Konstanten. Außerdem müssen Sie dies für eine verwenden, die Sie in einem Header deklariert haben und jetzt definieren.static const
: Am besten für dateispezifische (oder klassenspezifische) Konstanten.extern const
: Sie müssen dies verwenden, wenn Sie eine Konstante in einen Header exportieren.Sie müssen die Datei entweder in jede Datei, in der Sie sie verwenden, oder in den Präfix-Header importieren.
quelle
static NSString *const
in der.h
Datei verwenden?static NSString *const foo = @"foo";
, bestimmt Ihr Header, was die Zeichenfolge ist, und sie muss überall gleich sein. Wenn Sie die Zeichenfolge jemals ändern und verschiedene Parteien unterschiedliche Versionen des Headers mit einer anderen Zeichenfolge verwenden, stimmen die Zeichenfolgen beim Ausführen nicht überein Zeit. In einem Framework möchten Sie nur Zugriff auf das Symbol gewähren und das Framework als einzige Quelle für den wahren Wert dieses Symbols verwenden, damit jeder an einer Stelle dieselbe Zeichenfolge erhält. Dasextern
bringt dich.#define
s: Es wird nicht garantiert, dass sie dieselbe Adresse im Speicher haben (je nachdem, wie sie deklariert sind, können sie bei jeder Verwendung eine neue Instanz zuweisen), sodass die VerwendungmyObject == MyDefine
nicht immer wie erwartet funktioniert. abermyObject == MyStaticConst
wird.static NSString *const
statt zu buchstabierenstatic NSString const*
? Irgendwelche Unterschiede ?!static NSString const *
ist dasselbe wiestatic const NSString *
und bedeutet "ein (veränderbarer) Zeiger auf einen konstanten NSString" - was hier etwas nutzlos ist, da NSString bereits unveränderlich ist. Was Sie nur wollenstatic NSString * const
- was ein "konstanter Zeiger auf einen NSString" istFOUNDATION_EXPORT
Erwägen Sie die Verwendung
FOUNDATION_EXPORT
für etwas mehr Kompatibilität alsextern
in Foundation definiert und in kompatiblen Formaten für C, C ++ und Win32 kompiliert.Wie in NSObjCRuntime.h definiert
quelle