Equivalent of public static final variables

Andrew S picture Andrew S · Feb 16, 2013 · Viewed 10k times · Source

I understand that placing the word extern before a variable declaration in a header file declares the existence of a global static variable without initialising it. I also understand that if I import the file containing the extern variables, I can reference them without a class/file name. But where does one define them and their values?

What I am trying to do is create a class of constants with global constants that I want to use throughout an iOS application's code.

Does one put them inside the interface like this?

Example.h

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

extern   NSString * const PREFS_NAME;

}

Or does one put then outside of the interface like this

Example.h

#import <Foundation/Foundation.h>

extern   NSString * const PREFS_NAME;    

@interface Constraints : NSObject
{

}

Then in the implementation .m file how would one initialise the extern values?

Inside the implementation area like this?

Example.m

#import "Constraints.h"

@implementation Constraints

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

@end

Or do initialise them outside of the implementation area like this:

Example.m

#import "Constraints.h"

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

@implementation Constraints

@end

Or do I provide them their initial values in a constructor? or some arbitrary a static style method with + in front of it i.e. +(void) setAppConstraints;

I have tried several combinations, but always run into errors, such as "Redefinition of 'xVariable' with a different type". Or a something about "extern does not have an initialise interface" (or something like that, I forget). So I want to know how to declaire and initialise them properly to form the same role as public static final variables in Java.

Also what are the limits of the extern command? I know I can extern an NSInteger or NSString, but what about NSArray?

I am asking this question because there seems to be to much misleading, or incomplete, information regarding the use of extern in Objective-C. Many of the answers seem speculatory. My hope is for this question to be a good resource not only for me, but to limit further similar questions about the basics of extern.

Answer

Ramy Al Zuhouri picture Ramy Al Zuhouri · Feb 16, 2013

You define it's value in the file inside which it's declared, which in your case is Example.m; You can still re-assign this variable, so the declaration in Example.h would look like this:

extern  NSString * PREFS_NAME;

This way every file that imports Example.h has access to this variable. The equivalent of public static final in Objective-C is const. If you also want it to be public you should make it be a class instance variable, but in this case you don't need it because it's already accessible everywhere. So in this case it would be:

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

Also notice that const NSString* is different from NSString* const. The latter is a const pointer to NSString. The former hasn't sense even if it's a correct syntax. In Objective-C the const qualifier doesn't affect objects, instead there are mutable and immutable classes. It would have sense in C++ meaning that you can use just const methods on the instance.