Where various variable and method types should be

2020-02-13 07:14发布

问题:

I've noticed that I get compilation errors if I place certain declarations in certain places in my header file. I've put comments into the code as to where I think certain things go; are they correct?

@interface Level : CCNode { 
    //Instance variables?
    PlayBackgroundLayer* playBGLayer;
    PlayUILayer* playUILayer;
    PlayElementLayer* playElementLayer;
}

//Static methods?
+(void) InitLevel: (int) levelNumber;
+(Level*) GetCurrentLevel;

//Property declarations for instance variables?
@property (nonatomic, retain) PlayBackgroundLayer* playBGLayer;
@end

//Static variables?
Level* currentLevel;
PlayTilemapLayer* playTilemapLayer;

回答1:

You are correct on all counts except one. Your last variables are not static variables, they are global variables. Static variables are simply variables that are declared with the static keyword and they mean something a little different than other languages. They aren't class variables, they are variables that are visible only to the file that they are declared in, and only then in the scope that it was declared (if you declare it inside a function other functions won't see it). However, as you would expect, they are only declared once regardless of how many instances you have. If you declare something outside an interface without the static keyword as you did, other classes will import them. However, this is not the ideal way to accomplish this (you might get redefinition errors if more than one class imports this header).

Also, one caveat, is that properties don't need to have an explicit backing variable (the compiler will create one for you if you use the @synthesize keyword), but of course if you desire one there is nothing wrong with it.

Finally, you should note that the only reason that your static methods class methods are not instance methods is because they start with a plus (+) character as opposed to a minus (-) character.



回答2:

Instance variables usually don't need to be declared explicitly. They're created when you @synthesize the property. If you do want them, though, the (new) correct place* is at the top of the implementation block:

@implementation Level
{
    PlayBackgroundLayer* playBGLayer;
    PlayUILayer* playUILayer;
    PlayElementLayer* playElementLayer;
}

Those aren't static methods, they're class methods, but, yes, that's where you declare them. Some people like to put @property declarations before the class methods, but that's a matter of opinion. Instance methods go after both of these, although technically speaking the order doesn't matter -- that is, the compiler doesn't care, it's just a matter of readability.

Those top-level variables need to go somewhere other than a header file, though. If you put them there you will get compilation errors because every file that imports the header will appear to be re-declaring storage for those variables, which isn't allowed.

Ususally you put such variables into a .m file. If you want them to only be visible from there, you would use static. If you want them visible from other files that import the header, you leave static off and declare the variable as extern in the header:

extern Level* currentLevel;

This lets the compiler know that the storage for the variable is reserved elsewhere.


*See "Class Interface" in TOCPL.