Archive

Tutoriale

Zauwazylem, ze czesc moich znajomych programistow nie jest przekonana, co do sposobu prawidlowego definiowania stanych w Objective-C. Wiekszosc osob uznaje wyzszosc uzycia stalych w stosunku do makra #define. Jednak sam sposob deklaracji stalej budzi watpliwosci.

W przypadku stalych, ktore maja byc widoczne w wielu plikach .m, sytuacja jest prosta – deklarujemy stale w pliku .h, wykorzystujac slowo kluczowe ‚extern’. W pliku implementacji .m przypisujemy im wartosc:

// Const.h
extern const int constantAccessibleFromMultipleFiles;

// Const.m
const int constantAccessibleFromMultipleFiles = 55;

W przypadku definiowania literalu, kod bedzie wygladal podobnie:

// LiteralConst.h
extern NSString *const literalConstant;

// LiteralConst.m
NSString *const literalConstant = @"I haz code";

NSString *const oznacza staly wskaznik na napis, NSString const* byloby z kolei wskaznikiem na stala (mozna przypisac do niego inna stala w trakcie wykonania programu).

Jakie zastosowac podejscie, kiedy chcemy, aby stala widoczna byla tylko w jednym pliku? Deklarujemy ja na poczatku pliku impementacji *m. Ale w jaki sposob?

Mamy dwie mozliwosci:

// ImplementationFileConstOne.m
NSString *const implementationFileConstOne = @"one";

albo:

// ImplementationFileConstTwo.m
static NSString *const implementationFileConstTwo = @"two";

Prawidlowa jest opcja druga. Czesc osob nie jest jednak przekonana i czesto pomija slowo kluczowe ‚static’ przy deklaracjach stalych w plikach .m. Czy ten blad ma jakies uzasadnienie?

Otoz ma. W jezyku C++ nie ma roznicy pomiedzy stala deklarowana przy uzyciu slowa kluczowego ‚static’ oraz bez niego. Bardziej precyzyjnie: w C++ stale globalne sa domyslnie statyczne. Oznacza to, ze linkowanie jest ograniczone do jednej jednostki translacji (jednego pliku cpp, ‚internal linkage’).

 
// OffsetConsts.cpp
const int offset = 20;

// OffsetConstsEquivalent.cpp
static const int offset = 20;

Oznacza to rowniez, ze w C++ nawet bez uzycia slowa kluczowego ‚static’, mozliwe jest deklarowanie stalych o identycznych nazwach (w roznych plikach .cpp). Nawet jesli przypiszemy do nich inne wartosci, nie spowoduje to bledu linkowania.

// ConstantsFileOne.cpp
const int offset = 10;

// ConstantsFileTwo.cpp
const int offset = 30;

W jezyku C jednak zachowanie jest inne. Stale globalne nie sa domyslnie statyczne. Proba zdefiniowania niestatycznych stalych w wielu plikach .c, spowoduje blad linkowania. Rozwiazaniem jest definiowanie stalych jako statyczne w plikach .c:

// ConstantsInCFileOne.c
static const int offset = 10

// ConstantsInCFileTwo.c
static const int offset = 30;

Powyzszy przyklad zostanie zlinkowany bez bledow.

Jak wyglada sytuacja w Objective-C? Jezyk ten jest rozszerzeniem C, maja zatem zastosowanie takie same zasady. Stala zdefiniowana bez uzycia slowa ‚static’ bedzie miala inny zakres linkowania, niz stala statyczna. Jesli w kilku roznych plikach zdefiniujemy stale o identycznej nazwie i zapomnimy dodac slowko kluczowe ‚static’, otrzymamy w rezultacie blad linkera.

Warto wiec zapamietac, ze stale definiowane w plikach implementacji w Objective-C nalezy poprzedzac keywordem ‚static’, natomiast w C++ nie jest to konieczne.