farhadf
farhadf

Reputation: 1978

Why are instance variables defined in the header file in Objective-C

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?

Upvotes: 7

Views: 4972

Answers (6)

Trashpanda
Trashpanda

Reputation: 14798

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

Upvotes: 5

Dietrich Epp
Dietrich Epp

Reputation: 213328

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.

Upvotes: 9

Peter N Lewis
Peter N Lewis

Reputation: 17811

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.

Upvotes: 2

Sijmen Mulder
Sijmen Mulder

Reputation: 5819

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)

Upvotes: 6

Alex Rozanski
Alex Rozanski

Reputation: 38005

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.

Upvotes: 3

Nick Stamas
Nick Stamas

Reputation: 1871

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

Upvotes: 6

Related Questions