公共静态最终变量的等价物

时间:2013-02-16 18:55:48

标签: objective-c syntax extern variable-declaration

我理解在头文件中将变量声明放在extern之前声明了全局静态变量的存在而没有初始化它。我也明白,如果我导入包含extern变量的文件,我可以在没有类/文件名的情况下引用它们。但是,人们在哪里定义它们及其价值?

我要做的是创建一个具有全局常量的常量类,我想在整个iOS应用程序的代码中使用它。

是否有人将它们放在界面中?

example.h文件

#import <Foundation/Foundation.h>
@interface Constraints : NSObject
{

extern   NSString * const PREFS_NAME;

}

或者那个人就像这样放在界面之外

example.h文件

#import <Foundation/Foundation.h>

extern   NSString * const PREFS_NAME;    

@interface Constraints : NSObject
{

}

然后在实现.m文件中如何初始化extern值?

在这样的实施区域内?

Example.m

#import "Constraints.h"

@implementation Constraints

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@end

或者在实现区域之外初始化它们,如下所示:

Example.m

#import "Constraints.h"

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@implementation Constraints

@end

或者我是否在构造函数中为它们提供了初始值?或者一些任意的静态样式方法,前面有+,即+(void) setAppConstraints;

我尝试了几种组合,但总会遇到错误,例如“使用不同类型重新定义'xVariable'”。或者关于“extern没有初始化界面”的东西(或类似的东西,我忘了)。所以我想知道如何正确地声明和初始化它们以形成与Java中public static final变量相同的角色。

extern命令的限制是什么?我知道我可以extern NSIntegerNSString,但NSArray呢?

我在问这个问题,因为在Objective-C中使用extern似乎有很多误导或不完整的信息。许多答案似乎都是猜测性的。我希望这个问题不仅对我来说是一个很好的资源,而且是为了限制关于extern基础的更多类似问题。

2 个答案:

答案 0 :(得分:13)

您在声明它的文件中定义它的值,在您的情况下是Example.m;您仍然可以重新分配此变量,因此Example.h中的声明如下所示:

extern  NSString * PREFS_NAME;

这样,导入Example.h的每个文件都可以访问此变量。 Objective-C中公共静态final的等价物是const。如果你也希望它是公共的,你应该把它变成一个类实例变量,但在这种情况下你不需要它,因为它已经可以在任何地方访问。所以在这种情况下它将是:

// .m file
NSString* const PREFS_NAME = @"MyApp_Prefs";
// .h file
extern NSString* const PREFS_NAME;

另请注意,const NSString *与NSString * const不同。后者是指向NSString的const指针。即使它是正确的语法,前者也没有意义。在Objective-C中,const限定符不影响对象,而是有可变和不可变的类。它在C ++中有意义,意味着你可以在实例上使用const方法。

答案 1 :(得分:3)

extern用于通知编译器您将使用另一个编译单元中定义的变量或函数。

当您说extern const NSString *PREFS_NAME时,您说“将此编译单元中的所有引用替换为PREFS_NAME”,因为它是在另一个文件中定义的变量PREFS_NAME。因此,当您尝试在.m中分配PREFS_NAME时,您所做的只是尝试分配一个变量,尽管它有一个名称,但它不存在。声明变量extern只是变量或函数的声明,而不是该变量或函数的定义。它让编译器知道 name 正在使用中,并且链接器将负责如何处理它,但即使你在这里提供了一个类型,它实际上并没有留出空间对于变量,它期望在实际定义变量的编译单元中留出空间。

您可以一起编译三个或四个不同的源代码文件,其中三个可以声明:

extern int buffer[];

可以宣布

int buffer[BUFSIZE];

在其全局范围内,链接器的工作是将对extern buffer的三个声明引用解析为第四个缓冲区的实际定义。

extern对于C变量和函数来说就像@class对于Objective-C类一样,它是一个前向声明,对编译器的承诺,当你看到它时你不必惊慌失措这里的名称未定义,因为链接器将回答您可能遇到的任何遗留问题。