Objective-C const常量的優雅使用方法
正文
在編寫代碼時經常要使用常量,來替代 magic number。比較簡單的做法是通過預處理指令 #define
來實現。
#define ANIMATION_DURATION 0.3
上述預處理指令會在編譯時的預處理階段會將代碼中 ANIMATION_DURATION
字符串替換為 0.3
。這種定義常量的方式比較簡便,但是存在兩個問題:
- 丟失瞭類型信息。
- 若該預處理指令聲明在頭文件中,引入該頭文件的代碼,
ANIMATION_DURATION
都會被替換,可能出現沖突。
Objective-C 的常量聲明方式
幸運的是,Objective-C
中提供瞭 const
關鍵字,可以用來定義常量。const
關鍵字可以對變量加以限定,使其值不能被改變,在整個作用域中都保持固定。
const NSTimeInterval kAnimationDuration = 0.3;
這種方式定義的常量包含類型信息,且在編譯時即可檢查是否與其他常量出現沖突。如果試圖修改由 const
修飾符所聲明的變量,那麼編譯器就會報錯。
如果常量僅在某個實現文件中使用,還應該加上 static
關鍵字,否則會被視為全局常量。若不使用 static
,編譯器會為它創建一個外部符號,若另一個編譯單元中也聲明瞭同名變量,就會報錯。
static const NSTimeInterval kAnimationDuration = 0.3;
當一個變量同時使用瞭 static
和 const
,那麼編譯器並不會創建符號,而是會像 #define
預處理指令一樣,把所有遇到的變量替換為常值。
有時候需要把一個常量暴露給外界使用,比如通知,此類常量需放在全局符號表中。可以使用 extern
關鍵字,在頭文件中進行聲明:
// .h extern NSString * const AFNetworkingTaskDidResumeNotification; // .m NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
該常量在頭文件中聲明,在實現文件中定義。需要註意的是 const
寫在指針類型的右邊意味著該指針的指向不可被改變,若寫在左邊意味著該指針指向的內容不可被改變。
按上述方式實現並定義後,在編譯時生成目標文件時,編譯器會在數據段為字符串分配存儲空間。
在 Foundation
框架中,蘋果為瞭兼容 C++
中對 extern
的使用,提供瞭宏:
#if defined(__cplusplus) #define FOUNDATION_EXTERN extern "C" #else #define FOUNDATION_EXTERN extern #endif #define FOUNDATION_EXPORT FOUNDATION_EXTERN #define FOUNDATION_IMPORT FOUNDATION_EXTERN
一個 C++
程序中可能包含其他語言編寫的部分代碼,同樣,C++
編寫的代碼片段也可能被用在其他語言編寫的代碼中。但是,不同語言編寫的代碼相互調用是困難的,更何況用同一種語言編寫,使用不同編譯器進行編譯的情況。因為,不同語言或者同種語言在不同編譯器上編譯時,在註冊變量,傳遞參數和參數在棧上的佈局上可能存在差異。
為瞭使它們遵守統一規則,可以使用 extern
指定一個編譯和鏈接規約。extern "C"
指令中的 C
,表示的是一種編譯和鏈接規約,而不是一種語言。C
表示符合 C
語言的編譯和鏈接規約的任何語言。
還要說明的是,extern "C"
指令指定的編譯和鏈接規約,不會影響語義,隻是改變編譯和鏈接的方式。
而 FOUNDATION_EXPORT
和 FOUNDATION_IMPORT
是用來兼容 Win32
應用程序的,移動端開發可以忽略。
所以上述對全局常量的聲明,可以寫成:
// .h FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification; // .m NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
在 Objective-C 中使用 let 來聲明常量
使用過 Swift
的同學,一定對其聲明常量的方式的簡潔性印象深刻,在 Swift
中聲明常量的方式如下所示:
let kAnimationDuration = 0.3
之所以能如此簡潔,是因為 Swift
具有 let
關鍵字和類型推斷的能力,但其實在 Objective-C
中也可以通過類似的方式來書寫常量。
Objective-C
中有一個關鍵字,是 __auto_type
,可以實現類似 Swift
中類型推斷能力的關鍵字,如下所示:
const __auto_type kAnimationDuration = 0.3;
可能對於簡單的數據類型,這樣的優勢不是很明顯,但是對於具有復雜泛型的類型來說,可以說優勢很大瞭:
// 舊方式 NSArray<NSDictionary<NSString *, NSString *> *> *models = ...; // 新方式 __auto_type models = ...;
同時,可以通過宏的方式,來減少 __auto_type
的書寫,即可實現通過 let
聲明常量,var
聲明變量。其中 auto 關鍵字是為瞭兼容 C++。
#if defined(__cplusplus) #define let auto const #else #define let const __auto_type #endif #if defined(__cplusplus) #define var auto #else #define var __auto_type #endif
聲明瞭上面的宏之後,就可以直接使用瞭:
let kAnimationDuration = 0.3;
以上就是Objective-C const常量的優雅使用方法的詳細內容,更多關於Objective-C const常量的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- C++內存模型和名稱空間詳解
- C++如何調用已經寫好的C接口
- C/C++實操True and false詳解
- C++11, 14, 17對tuple元素的訪問詳情
- C語言的程序環境與預處理你真的瞭解嗎