Class variable defined at @implementation rather than @interface?
I'm new to Objective-C, but I am curious about something that I haven't really seen addressed anywhere else.
Could anyone tell me what is the difference between a private variable that is declared at the @interface
block versus a variable that is declared within the @implementation
block outside of the class methods, i.e:
@interface Someclass : NSObject {
NSString *forExample;
}
@end
vs.
@implementation Someclass
NSString *anotherExample;
-(void)methodsAndSuch {}
@end
It seems both variables ( forExample
, anotherExample
) are equally 开发者_StackOverflow中文版accessible throughout the class and I can't really find a difference in their behaviour. Is the second form also called an instance variable?
The latter is not defining an instance variable. Rather, it is defining a global variable in the .m file. Such a variable is not unique to or part of any object instance.
Such globals have their uses (roughly equivalent C++ static members; e.g. storing a singleton instance), but normally you would define them at the top of the file before the @implementation directive.
They're very different! The one in @implementation
is a global variable not unique to each instance. Imagine there were accessors for both variables, written in the obvious way. Then the difference in behavior is shown here:
Someclass* firstObject = [[Someclass alloc] init];
Someclass* secondObject = [[Someclass alloc] init];
//forExample is an instance variable, and is unique to each instance.
[firstObject setForExample:@"One"];
[secondObject setForExample:@"Two"];
NSLog(@"%@",[firstObject forExample]); //Result: "One"
NSLog(@"%@",[secondObject forExample]); //Result: "Two"
//anotherExample is a global variable, and is NOT unique to each instance.
[firstObject setAnotherExample:@"One"];
[secondObject setAnotherExample:@"Two"];
NSLog(@"%@",[firstObject anotherExample]); //Result: "Two" (!)
NSLog(@"%@",[secondObject anotherExample]); //Result: "Two"
//Both instances return "Two" because there is only ONE variable this time.
//When secondObject set it, it replaced the value that firstObject set.
If you are looking for this sort of behavior, you might be better off using a class variable, like this:
static NSString* yetAnotherExample = nil;
Then you can use class methods to interact with the variable, and it's clearly class-specific (as opposed to instance-specific or global).
If you declare a variable inside the @implementation section, you're actually creating a global variable, visible everywhere (in every method in your application).
Member variables can only be declared in the @interface section. They are only accessible in the class itself.
The private block declared inside the @implementation
block is kind of dangerous, seems to me, comparing with other OOP concept e.g. Java. Its look like member variable but kinda static.
Novice programmer can easily fooled with it. I write a test program and surprised with the behaviour.
@interface SomeClass : NSObject
{
NSString *forExample;
}
- (void) set:(NSString *)one another:(NSString *)another;
- (void)print;
@end
Implementation:
#import "SomeClass.h"
@implementation SomeClass
NSString *anotherExample;
- (void) set:(NSString *)one another:(NSString *)another
{
forExample = one;
anotherExample = another;
}
- (void)print{
NSLog(@"One = %@, another = %@", forExample, anotherExample);
}
@end
Test:
- (void)testClass {
SomeClass * s1 = [SomeClass new];
[s1 set:@"one one" another:@"one another"];
SomeClass *s2 = [SomeClass new];
[s2 set:@"two one" another:@"two another"];
[s1 print];
[s2 print];
}
And the output is,
One = one one, another = two another
One = two one, another = two another
Use a code snippet to tell the difference between a member variable and a global variable:
@implementation MyClass {
// It is an ivar, or called member variable
// Can NOT be initialized when defined.
// Can be accessed with `self->_i`
int _i;
}
- (instancetype)init {
if (self = [super init]) {
_i = 2; // should be initialized before being used.
}
return self;
}
int i = 9; // Global variable, and can be initialized when defined.
- (void)myFun {
NSLog(@"%i, %i", self->_i, i);
}
@end
// Another file
extern int i;
NSLog(@"%i", i);
Just to be clear, never ever ever declare an IBOutlet as a global var (in the implementation) if you are using it for localized nibs/xibs.
I spent a few hours figuring why the outlet is connectable only in one of the localized nibs at any given time.
Thanks for this question and the answers!
精彩评论