tags:

views:

398

answers:

5

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 through messages?

+5  A: 

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

Nick Stamas
+3  A: 

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.

Perspx
+6  A: 

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)

sjmulder
They are just C structs, not even fancy ones :-) so something like anObject->anIVar works just fine. Unfortunately, the legacy runtime allows this kind of access even on @private variables and just vomits a compiler warning :-/
Jason Coco
+2  A: 

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.

Peter N Lewis
You can, however, declare a property in a continuation and @synthesize it in the main @implementation.
Ahruman
+2  A: 

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.

Dietrich Epp