Class variable defined at @implementation rather than @interface?

后端 未结 6 2051
夕颜
夕颜 2020-11-29 02:46

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

相关标签:
6条回答
  • 2020-11-29 03:17

    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.

    0 讨论(0)
  • 2020-11-29 03:19

    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!

    0 讨论(0)
  • 2020-11-29 03:20

    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
    
    0 讨论(0)
  • 2020-11-29 03:25

    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.

    0 讨论(0)
  • 2020-11-29 03:28

    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);
    
    0 讨论(0)
  • 2020-11-29 03:40

    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).

    0 讨论(0)
提交回复
热议问题