Tworzę klienta Reddit do celów edukacyjnych. Muszę mieć plik ze stałymi. Myślałem o zaimportowaniu pliku do Reddit-Prefix.pch
pliku, aby stałe były dostępne dla wszystkich plików. Czy to dobry sposób na robienie rzeczy? Ponadto przeprowadziłem badania i znalazłem kilka metod tworzenia stałych, ale nie wiem, której użyć:
#define
makroconst
static const
extern const
enum
Więc który sposób jest preferowany? Jaka jest konwencja? Wiem, że „to zależy”, ale moje pytanie jest bardziej szczegółowe: Jakie są przypadki użycia każdego z tych rozwiązań?
Ponadto, jeśli używam extern const
, czy muszę importować plik, czy też stałe będą dostępne globalnie bez importowania pliku?
Jedna rzecz, którą mogę logicznie wywnioskować, enum
to najlepszy wybór przy definiowaniu czegoś takiego jak niestandardowe domeny błędów (czy rzeczywiście mam rację?). A co z innymi?
źródło
enum
jest użyteczne tylko dla wartości całkowitych.#define
a stałe mogą być dowolnym typem danych.const
,static const
iextern const
są takie same z wyjątkiem zakresu. Więc tak naprawdę są tylko trzy możliwości.Odpowiedzi:
Pierwsze pytanie dotyczy zakresu, w jakim chcesz mieć swoje stałe, czyli tak naprawdę dwa pytania:
Jeśli są specyficzne i wewnętrzne dla jednej klasy, zadeklaruj je jako
static const
na początku pliku .m, na przykład:Jeśli odnoszą się do pojedynczej klasy, ale powinny być publiczne / używane przez inne klasy, zadeklaruj je tak, jak
extern
w nagłówku i zdefiniuj je w .m:Jeśli powinny być globalne, zadeklaruj je w nagłówku i zdefiniuj w odpowiednim module, szczególnie dla tych stałych.
Możesz je łączyć i dopasowywać dla różnych stałych o różnych poziomach globalności, które chcesz, aby były, oraz dla różnych stałych globalnych, które po prostu nie pasują do siebie - możesz umieścić je w osobnych modułach, każdy z własnym nagłówkiem, jeśli chcieć.
Dlaczego nie
#define
?Stara odpowiedź brzmi: „makra nie mają informacji o typie”, ale dzisiejsze kompilatory są całkiem sprytne, jeśli chodzi o sprawdzanie typów literałów (do jakich makr rozwijają się), a także zmiennych.
Nowoczesna odpowiedź brzmi, ponieważ debugger nie będzie wiedział o twoich makrach. W
[myThing addObserver:self forKey:MyThingNotificationKey]
poleceniu debugera nie można powiedzieć, czyMyThingNotificationKey
jest to makro; debugger może o tym wiedzieć tylko wtedy, gdy jest to zmienna.Dlaczego nie
enum
?Cóż, rmaddy pobił mnie w komentarzach:
enum
może definiować tylko stałe całkowite. Rzeczy takie jak numery identyfikatorów seryjnych, maski bitowe, kody czterobajtowe itp.Do tych celów
enum
jest świetny i absolutnie powinieneś go używać. (Nawet lepiej wykorzystywać teNS_ENUM
iNS_OPTIONS
makra ). W przypadku innych rzeczy, to trzeba użyć czegoś innego;enum
nie robi nic poza liczbami całkowitymi.I inne pytania
Prawdopodobnie nieszkodliwe, ale prawdopodobnie przesadne. Zaimportuj swoje nagłówki stałych tam, gdzie ich potrzebujesz.
#define
: Dość ograniczone. Szczerze mówiąc, nie jestem pewien, czy jest już dobry powód, aby używać tego do stałych.const
: Najlepsze dla stałych lokalnych. Musisz także użyć tego dla tego, który zadeklarowałeś w nagłówku i teraz definiujesz.static const
: Najlepsze dla stałych specyficznych dla plików (lub klas).extern const
: Musisz tego użyć podczas eksportowania stałej w nagłówku.Musisz zaimportować plik w każdym pliku, w którym go używasz, lub w nagłówku prefiksu.
źródło
static NSString *const
w.h
pliku w ogóle?static NSString *const foo = @"foo";
, to twój nagłówek określa, co to jest ciąg i musi być wszędzie taki sam - jeśli kiedykolwiek zmienisz ciąg i różne strony używają różnych wersji nagłówka z innym ciągiem, wówczas ciągi nie będą pasować podczas wykonywania czas. We frameworku chcesz zapewnić dostęp tylko do symbolu i pozwolić, aby struktura była jedynym źródłem prawdziwej wartości tego symbolu, aby każdy mógł uzyskać ten sam ciąg z jednego miejsca. To właśnieextern
cię dostaje.#define
s: nie ma gwarancji, że mają ten sam adres w pamięci (w zależności od tego, jak są zadeklarowane, mogą przydzielać nową instancję za każdym razem, gdy są używane), więc używaniemyObject == MyDefine
nie zawsze będzie działać zgodnie z oczekiwaniami, alemyObject == MyStaticConst
będzie.static NSString *const
zamiaststatic NSString const*
?? Jakieś różnice ?!static NSString const *
jest tym samym costatic const NSString *
i oznacza „(zmienny) wskaźnik do stałego NSString” - co jest tutaj trochę bezużyteczne, ponieważ NSString jest już niezmienny. Tylkostatic NSString * const
to, czego chcesz - czyli „stały wskaźnik do NSString”FOUNDATION_EXPORT
Rozważ użycie,
FOUNDATION_EXPORT
aby uzyskać nieco większą kompatybilność, niżextern
ponieważ jest zdefiniowana w fundamencie i kompiluje do kompatybilnych formatów dla C, C ++ i Win32.Zgodnie z definicją w NSObjCRuntime.h
źródło