I can understand defining the functions in the @interface of the header file, but why the instance variables? Shouldn\'t the instance variables be private, only accessible
The reason is so it can calculate offsets of variables for subclasses.
@interface Bird : NSObject {
int wingspan;
}
@end
@interface Penguin : Bird {
NSPoint nestLocation;
Penguin *mate;
}
@end
Without knowing the structure of the "Bird" class, the "Penguin" class can't calculate the offset of its fields from the beginning of the structure. The penguin structure looks kind of like this:
struct Penguin {
int refcount; // from NSObject
int wingspan; // from Bird
NSPoint nestLocation; // from Penguin
Penguin *mate; // from Penguin
}
This has a side effect: if you change the size of a class in a library, you break all the subclasses in apps that link to that library. The new properties work around this problem.
Taken from the section of Apple's documentation on defining Objective-C classes, The Role of the Interface:
Although instance variables are most naturally viewed as a matter of the implementation of a class rather than its interface, they must nevertheless be declared in the interface file. This is because the compiler must be aware of the structure of an object where it’s used, not just where it’s defined.
In case anyone stumbles across this question -- as of XCode 4.2 with the LLVM compiler, you can declare instance variables in the @implementation using the following brace notation:
@interface SomeClass : NSObject
@end
@implementation SomeClass {
NSString *myInstanceVariable_;
}
- (void)moreMethods {}
@end
Instance variables generally shouldn't be part of your classes declared public interface -- they're implementation details.
However, MAKE SURE you define your instance variables within the braces or else you'll be defining a global variable that has no relation to the object instance:
@implementation SomeClass
NSString *whoopsGlobalVariable_;
- (void)moreMethods {}
@end
I think it is a technical issue. If I understand correctly, a Objective-C class is just a fancy C struct. And for a struct to be used its size must be known. (Like how would sizeof() work otherwise)
Although they are declared in the header file, all instance variable in Objective-C have @protected access by default. This means the variable is accessible within the class that declares it and any class inheriting from that class.
Here is Apple's documentation on defining an Objective-C class: Defining Classes
Notice the section titled "The Scope of Instance Variables".
Note that under the Objective C 2.0 new "Modern Runtime" (availabe in iPhone applications and 64-bit Mac OS X 10.5 applications) you do not need to specify the ivars, you can specify the properties and then use @synthesize to generate the ivars.
This is because in the Modern Runtime, ivars have a global indirection symbol that holds the offset for the ivar. This also resolves the fragile base class issue, allowing ivars to be reordered and added without requiring recompiling of subclasses (deleting or renaming ivars may still cause link errors).
However you still have to list properties in the main interface, so there does not seem to be any way to entirely hide private ivars which is unfortunate. You cannot, for example, use a property and @synthesize in a category.