oc繼承自c,c的變量聲明方式這裡就不說了,進入正題。
@interface中聲明成員變量
oc最原始的變量聲明,就是在@interface中聲明。預設的聲明方式就是隐性的@protected
@interface ClassA :NSObject
{
NSInteger oneInteger; //隐含@protected的意思
}
@end
oc中也支援繼承,是以如果想聲明私有變量,不允許子類通路該變量,可以 加 @private辨別符
@private
NSInteger oneInteger;
如果想聲明公有變量,想在對象的外部進行通路,可以這樣:
@public
NSInteger oneInteger;
//通路的方式如下
classA->oneInteger = 123;
後來蘋果又提供了一個新的聲明辨別@package,使變量隻能在framework内才是public。蘋果官方文檔摘抄如下
@package is a new instance variable protection class, like @public and @protected. @package instance variables behave as follows:
(@package是一個新的成員變量保護域,就像@public和@protected。使用@package作用域的成員變量,有如下特征:)
@public in 32-bit;
@public in 64-bit, inside the framework that defined the class;
@private in 64-bit, outside the framework that defined the class.
(在32位系統中,@package和@public等同
在64位系統中,framework内的@package變量,可以像@public變量一樣使用
在64位系統中,framework外不能通路@package變量,甚至繼承framework中的類都不可以,類似@private)
@property時代
後來有一本紅寶書,風靡一時,大家都看過吧,叫 《Objective-C.2.0程式設計》
在這本書中,介紹了屬性聲明@property以及存取器@synthesize。屬性聲明使得一個變量可以在對象外部進行通路,而存取器則預設生成了變量的setter和getter方法。
//頭檔案
@interface ClassA :NSObject
{
NSInteger oneInteger;
}
@property(nonatomic)NSInteger oneInteger;
@end
//實作檔案
@implementation ClassA
@synthesize oneInteger;
@end
這樣的話,想通路ClassA的變量就友善了許多
classA.oneInteger = 12; //setter方法設定變量
NSLog(@"%d", classA.oneInteger); //getter方法擷取變量
如果要隐藏成員變量名,還可以給變量取别名
//頭檔案
@interface ClassA :NSObject
{
NSInteger oneInteger; //成員變量
}
@property(nonatomic)NSInteger propertyInteger; //别名
@end
//實作檔案
@implementation ClassA
@synthesize propertyInteger = oneInteger; //别名,映射到成員變量上
@end
存取器預設生成setter和getter方法,如果有需要仍可以自定義,自定義的方法會覆寫系統生成的方法。setter和getter方法的定義規則:
//setter方法名為 set+首字母大寫的變量名 ,參數類型必須是變量的類型。
- (void)setOneInteger:(NSInteger)aInt;
//getter方法名與變量同名,傳回類型必須是變量的類型;
- (NSInteger)oneInteger;
聲明屬性時,還可以指定setter和getter的方法
@property(nonatomic,[email protected](setAnInteger:))NSInteger oneInteger;
此時,oneInteger的set方法就變成了 -(void)setAnInteger:(NSInteger)aInt;
後來蘋果推出新特性,允許不聲明變量,隻寫@property和@synthesize。
//頭檔案
@interface ClassA :NSObject
@property(nonatomic)NSInteger oneInteger;
@end
//實作檔案
@implementation ClassA
@synthesize oneInteger;
@end
此時編譯器預設幫助生成一個變量,與@property同名。即,預設生成了一個NSInteger oneInteger;
如果在不聲明變量的情況下,存取器使用别名,則聲明的變量名與=後面的名字相同。
@synthesize oneInteger = abc; //生成的變量為abc
除了可以不聲明變量,甚至存取器都可以省略了
//頭檔案
@interface ClassA :NSObject
@property(nonatomic)NSInteger oneInteger;
@end
此時有所不同的是,預設生成的變量名為 下劃線+屬性名。即,預設生成了一個NSInteger _oneInteger;
在特殊的匿名分類Category中聲明變量
oc中的分類大家都用過,分類不允許聲明成員變量,可以聲明屬性和方法。
以ClassA為例,可以聲明一個分類
@interface ClassA (Category1)
@property(nonatomic)NSInteger cateInt; //允許聲明@property
- (void)cateFunc; //允許聲明方法
@end
使用分類,使得隐藏@property成為可能,将Category寫在.m檔案中,則其他檔案都無法通路到,相當于變相的@private。
但是有一個特殊的分類,不寫分類名,稱之為 匿名分類。匿名分類的一個重要特征,就是允許聲明成員變量,且預設@private熟悉
@interface ClassA ()
{
NSInteger cateInt; //匿名分類,允許聲明成員變量
}
@end
當然,可以使用@protected等辨別來改變它的作用域。
在@implementation中聲明變量
蘋果對變量的作用域一直如此糾結,現在又推出一種新的變量聲明方式,變量聲明在實作檔案@implementation中。這樣就變成了隻能在對象内使用,相當于@private。
//頭檔案
@interface ClassA :NSObject
@end
//實作檔案
@implementation ClassA
{
NSInteger oneInteger; //相當于私有變量 @private
}
@end
以上就是幾種變量的聲明方式,真是走馬觀燈,眼花缭亂。
不過在日常開發中,一半較少遇到變量作用域的問題,正常使用就好。這些各種各樣的方式,還是留給有需要的人去用吧。