作用域

1.控制实例变量作用域的指令

在接口中声明实例变量可通过子类进行继承,继承来的实例变量同样可以通过变量名来在子类定义的方法中直接进行访问。在接口部分进行声明实例变量时,可以把以下的指令放在实例变量之前,以便精确控制其作用域:

@protected:

这个指令后面的实例变量可被类及任何子类中定义的方法直接访问。这个是默认情况

@private:
这个指令后面的实例变量可被定义在该类的方法直接访问,但不能被子类中定义的方法直接访问
@public:
这个指令后面的实例变量可悲该类中定义的方法直接访问,也可被其他类或者模块中定义的方法访问
@package:
对于64位图像,可以在实现该类的图像的任何地方访问这个实例变量。(啥意思?)
一个Printer类,包含两个私有实例变量pageCount和tonerLevel,且只能在该类中被访问
Printer.m
@interface Printer: NSObject
{
@private
   int pageCount;
   int tonerLevel;
@protected
   //other instance variables
}
...
@end

这些特殊的指令就像“开关”一样,所有出现在这些指令之后的变量(直到标志着变量的声明结束的右花括号为止)都有指定的作用域,除非使用另一个指令。将实例变量声明为public并不是良好的编程习惯,因为这违背了数据封装的思想(即一个类要隐藏它的实例变量)。

关于属性、存取方法和实例变量

编程规范目前的趋势是使用下划线(—)作为实例变量名字的起始符。遇到如下指令:

@synthesize window = —window;

表明合成属性window的取值方法和设置方法,并将属性与实例变量—window(没有显示声明)关联起来。这样有利于区别属性和实例变量,比如:

[window makeKeyAndVisible];无法运行,因为没有实例变量名为window。而使用

[_window makeKeyAndVisible];或者最好你使用获取函数[self.window makeKeyAndVisible];可行;

在实现部分显示地声明地实例变量(或者@synthesize指令隐性声明地实例变量)是私有地,这意味着并不能在子类中通过名字直接获取实例变量。在子类中只能能使用继承地存取方式获取到实例变量地值。

2.全局变量

如果在程序地开始处(所有方法、类定义和函数定义之外)编写以下语句:

int gMoveNumber = 0;

gMoveNumber则被定义为全局变量,按照惯例,用小写g作为全局变量地首字母,也被定义为外部全局变量,外部变量可被其他任何方法或函数访问和更改其值的变量。在需要访问外部变量地模块中,变量声明和普通方式一样,只是需要在声明前加上关键字extern。这就告知系统,要访问其他文件中定义地全局变量。

处理外部变量时,变量可以在许多地方声明为extern,但是只能定义一次。记住,声明不会引起分配变量地存储空间,而定义会引起变量存储空间地分配。

例如:

main.m文件:

#import "Foo.h"
int gGlobalVar = 5; 全局变量
int main (int argc, char *argc[])
{
...
Foo *myFoo = [[Foo alloc] init];
NSLog (@"%i", gGlobalVar);
[myFoo setgGlobalVar: 100];
NSLog (@"%i", gGlobalVal);
..
}
-(void) setgGlobalVar: (int) val
{
extern int gGlobalVar;
gGlobalVar = val;
}
在前面程序中,gGlobalVar定义为全局变量,因此任何方法只要正确滴使用extern声明,都可以访问它。
结果是:
5
100
这就证明了方法setgGlobalVar:可以访问和改变外部变量gGlobalVar的值。

如果有很多方法需要访问gGlobalVar地值,只在文件地开始进行一次extern声明将比较简单。但是,如果只有一个或少数几个方法要访问这个变量,就应该在其中地每个方法中单独进行extern声明。

注意,如果变量定义在包含访问改变量的文件中,那么不需要单独进行extern声明。

3.静态变量

前面所介绍的例子与数据封装的原则以及良好的面向对象的编程技术相违背。我们希望定的全局变量只在特定的模块(文件)中是全局的,这种变量在某一种情况下很有意义,即除了特定类中的方法之外,在没有其他方法需要访问这个特定的变量。

如果语句

static  int  gGlobalVar = 0;

声明在任何方法(或函数)之外,那么在该文件中,所有位于这条语句之后的方法或函数都可以访问gGlobalVar的值,而在其他文件中的方法和函数则不行。而类方法不能访问实例变量,可是,你可能希望类方法可以设定和访问一些实例变量。例如:类的分配器方法,他要记录类已经分配空间的对象数目。实现这项任务的方式是在类的实现文件中设定静态变量,因此,分配器方法可以直接访问它。类的用户不知道这个变量,因为它是定义在实现文件中的静态变量,作用域只是文件内部。用户不能直接访问,如果要从类外访问实例变量,则可以编写一个方法来获取改变量。

在Fraction.h中添加这两个新的类的方法声明:

+ (Fraction *) allocF;

+     ( int) count;

Fraction.m 的实现文件为:

static int gCounter;

@implementation Fraction

+ (Fraction *) allocF

{

extern int gCounter;

++ gCounter;

return [Fraction alloc];

}

+ (int ) count 

{

extern int gCounter;

return gCounter;

}

. . .

@end

因为gCounter变量定义在该文件中,因此,不需要在这两个方法中使用extern声明。声明只是为了让阅读该方法的人明白,它访问呢的变量是定义在该方法之外。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值