Nosrettap
Nosrettap

Reputation: 11320

In Objective-C what is the difference between defining something (say a property) in the header file as opposed to the .m file?

In Objective-C what is the difference between defining something (say a property or a method) in the header file as opposed to the .m file? I've heard that it has something to do with making it public or private, but I'm not sure of the details. If this is the case, is this the same as public and private methods in Java?

I'm proficient at Java so any way that you can relate Objective-C to it would be helpful.

Thanks

EDIT: To clarify, suppose I have a class (if that's the proper term) called "CalculatorBrain", what is the difference between the following (pay attention to NSMutableArray *operandStack:

In the .m file:

 @interface CalculatorBrain()
 @property (nonatomic, strong) NSMutableArray *operandStack;
 @end

versus, in the .h file:

 @interface CalculatorBrain : NSObject
 @property (nonatomic, strong) NSMutableArray *operandStack;
 @end

What difference does it make where I define NSMutableArray *?

Upvotes: 6

Views: 2044

Answers (5)

user457812
user457812

Reputation:

Alright, following your clarification, I'll try to explain what's going on there.

Let's say you have this in your header (.h) file:

@interface Foobar {
}
@property (readonly) int numberOfPies;
@end

This define's a class's public interface. While I've said "public" there, I want to make it perfectly clear that Objective-C does not have the same concept of visibility that Java or C++ have (it employs it for instance variables, but that's the farthest it goes that I'm aware of). I've also bolded "class" because there's an important distinction coming up. The other thing I want to point out is that the class publicly declares the numberOfPies to be readonly, since that's also going to be important.

Now, let's look at the implementation (.m) file for this class:

@interface Foobar ()
- (void) doSomething;
@property (readwrite) numberOfPies;
@end

@implementation Foobar
@synthesize numberOfPies;

- (void) doSomething {
  NSLog(@"Doing something");
}

@end

Look at @interface Foobar () — this begins a class extension. It is not a class declaration. These are also sometimes called private categories, anonymous categories, or class continuations (according to zneak in a comment below), but the important thing to know is that they're basically a kind of category (I've linked to Apple's documentation on categories). These essentially define additional methods and properties and can be applied to any class whatsoever. They're used here is to provide what amounts to a private interface for the class (hence "private category").

Moving on, now we'll compare the numberOfPies property between the class and the category. If you didn't notice the difference yet, here it is: the class exposes it as readonly, the category expands this and makes it readwrite inside the implementation. When synthesizing the property, Obj-C will include both the getter and setter if this happens. The important thing here is that, aside from whether your property is readonly or readwrite, your property cannot change. It can't have the assign attribute in the class and copy in the category. This basically lets you define a convenient private setter for properties as well.

One important thing to note here is that absolutely nothing in that category is truly private. Nothing can stop you from sending the doSomething message to a Foobar object, though the compiler will give you a warning outside of the class's implementation file.

Following that, you have your standard implementation. This includes implementations for the methods in your anonymous category.

Upvotes: 4

zneak
zneak

Reputation: 138051

In the "purest" sense, the main difference is that the .h file is meant to be included in other files, so class members declared there are meant to be visible from the outside; the .m file is not meant to be included anywhere, and as such anything declared there will probably not be visible anywhere else.

In contrast to Java and other popular languages, a global symbol (be it a class, a structure, a function, or a variable) cannot be accessed unless it has been declared prior to its use. This is why hiding a declaration in a .m file makes it harder to access the symbol from the outside.

Upvotes: 0

justin
justin

Reputation: 104698

you only declare a property in the @interface. you define it in the @implementation.

the declaration publishes to the clients or compiler that the property exists, its type, and attributes.

the definition is the actual implementation. without a definition, an implementation will not exist. that is, you may expect a "does not respond to selector" exception without a definition.

This is just like you see in C:

// only a declaration
int fun(void);

// a definition
int fun(void) {
   ...
}

but you don't always get a linker error with ObjC.

What difference does it make where I define NSMutableArray *?

People often hide some of their declarations in a class extension (as in your sample), but it's really distinct from visibility (e.g. public, protected, private). The methods may still be externally called or members may be accessed via the runtime (and a few other cases). It's an attempt at encapsulation, but it is not as strong a guarantee as you'd find in other languages (Java or C++).

Upvotes: 0

millimoose
millimoose

Reputation: 39950

In C, you usually compile .c files (or, for Objective-C, .m files, they're analogous) one-by-one into blobs of native code. (These blobs are .o files.) When compiling a given .c file, the compiler does not look into the other .c files to see what functions are defined in them. What you can do, is give the compiler declarations (basically names and signatures) of functions that will be available later, when linking.

A .h file is basically a list of these declarations. It's a manifest of all the functions (methods etc.) in a .c file that can be called in other .c files. Therefore, it should usually only include what's needed in these other files. ("Public" functions.)

A second phase of building a C program is linking, when the .o files are merged together, and the references to functions between them are connected.

In Java, you have .class files; a class file holds both compiler-readable signatures of the methods of the class, and the bytecode of their implementations. An analogy to C would be that the Java compiler automatically extracts the headers that would go into a .h file, and includes them at the start of an .o file.

Because the same toolchain is used to build programs in both languages, Objective-C inherits this split from plain C, including splitting up the interface ("declaration") of a class and its implementation ("definition") between different files.

(The above is admittedly a gross oversimplification of the C way of doing things, and it's possible to set things up in very different ways. I believe the one C file to one header file convention is fairly conventional for ObjC though.)

Upvotes: 0

Seva Alekseyev
Seva Alekseyev

Reputation: 61351

The Objective C class system is unlike Java's - it separates declaration and definition. You define your properties in the .h file

@property(...) int X;

and then define its getter/setter (or synthesize) it in the .m file. Now, you don't have to declare them in the .h. Class consumers will still be able to access it, but the compiler will throw you a warning to the effect of "class may not support...". Such is the dynamic nature of the ObjC.

On the other hand, if you declare the property but don't define/synthesize it, the compiler will complain about your class being incomplete.

There's one exception to that rule. If the property is not declared but a getter/setter/@synthesize exists, the compiler will let you use it from inside the class implementation from the point it was defined down the file. It's not the same as Java's private access, since the property is still accessible (at the cost of a warning) from outside of the class. It's the closest thing to private access ObjC has to offer.

Upvotes: 1

Related Questions