I'm teaching myself Objective-C from a book (Cocoa programming for mac OS X) and am about halfway through however I have two questions that aren't answered or defined in the book.
When defining class methods what is the difference between (assuming there in a .h file):
- (int) population;
+ (int) population;
The way I see it at the moment is that - methods require the class to be allocated and initialized first however + can be called statically without requiring allocation and initialization. E.g. (in a function in another class)
// Using -
Earth *world = [[Earth alloc] init];
int population = [world population];
// Using +
int population = [Earth population];
If that is correct, when should I use static methods and are they're any disadvantages with doing so.
When defining a var in either a function paramater or as an actual var in a function, does the use of * mean the var will be an object? e.g. (again in a header file.)
- (void) setPopulation: (NSNumber *) population; //Use of * as population is of NSNumber
- (void) setPopulation: (int) population; // population isn't a class so doesn't need *
Sorry if any of my terms don't make sense in the land of Objective-C such as static methods, etc. I'm a PHP and Ruby Programmer.
The -/+ in method declarations for Objective-C simply denote whether the method is a class method or an instance method. For example, with Objective-C, you cannot send an instance a message that was declared as a class method. For example:
#interface MyObject : NSObject
-(void)myInstanceMethod;
+(void)myClassMethod;
#end
// ...
MyObject* obj = [[MyObject alloc] init];
[obj myInstanceMethod]; // this is okay
[obj myClassMethod]; // this will fail
[[obj class] myClassMethod]; // this is okay
[MyObject myClassMethod]; // this is okay
[MyObject myInstanceMethod]; // this will fail
As to the second part of your question, Objective-C is a strict super-set of C. It adds classes but they are really C data structures whose implementations are hidden from you by the Objective-C runtime. Because of this, classes are always represented as pointers. In C, the * means that the variable is being declared as a pointer to some memory address. You can use pointers with primitive types in C as well, but Objective-C objects must always be referred to by pointers.
There are many great tutorials/introductions to pointers out there. I would suggest simply googling for C tutorial and pointers to learn more.
The + declaration is a class method, you need no instance to call it. Constructors/factory methods need to be class methods. The - declared an instance method, operation on a single instance. Each instance has its own independent state (member variables). This is a fundamental difference in OO programming! In general make most methods instance methods, except for utility classes.
You can see some discussion of when to use static methods in When should I write Static Methods?
Related
I have been reading about Protocols on Objective-C but I cannot grasp this:
Consider this line
Person <CoordinateSupport> *person = [[Person alloc] init];
What is the purpose of declaring the variable to conform to the protocol CoordinateSupport? Is this something just for compile time, so Xcode can warn me if I assign something different to person or is there any purpose at run time?
I cannot see how a variable can conform to a protocol. OK, a class is easy to see, because you can have a protocol defining methods that you want some class to follow but an ivar?
I am not seeing it.
The standard pattern when declaring that a variable conforms to a protocol is to give it the "any object" type, id. Declaring that a variable both has a specific type and conforms to a protocol is typically redundant – I'll explain why later. For now, let's talk about variables of type id<P>, where P is some protocol, and why they're useful. This type should be read as "an instance of any class that conforms to P."
To concretize the discussion that follows, let's define a protocol:
#protocol Adder
- (NSInteger)add:(NSInteger)a to:(NSInteger)b;
#end
I cannot see how a variable can conform to a protocol.
This one is easy. A variable conforms to an Objective-C protocol when it represents an instance of a class that implements all of the required methods in the protocol.
#interface Abacus : NSObject <Adder>
#end
#implementation Abacus
- (NSInteger)add:(NSInteger)a to:(NSInteger)b { return a + b; }
- (NSInteger)beadCount { return 91; }
#end
Given this Abacus class, you could, of course, create a new Abacus:
Abacus *a = [[Abacus alloc] init];
NSLog(#"%ld", (long)[a add:5 to:6]); // 11
NSLog(#"%ld", (long)[a beadCount]); // 91
But you could also declare a to just be of type id<Adder. Remember, that means the type of a is "an instance of any class that conforms to Adder."
id<Adder> a = [[Abacus alloc] init];
NSLog(#"%ld", (long)[a add:5 to:6]); // 11
NSLog(#"%ld", (long)[a beadCount]); // Compile error: No known instance method for selector 'beadCount'
The compiler complains because all we said about the type of a is that it is a class that conforms to Adder, and nowhere in the Adder protocol do we say anything about a method named beadCount.
What is the purpose of declaring the variable to conform to [a protocol]?
The purpose is for information hiding. When you want a class that conforms to Adder, you don't need to care about what the actual class is – you just get an id<Adder>. Imagine that Abacus is a system class, and you've written the following code:
- (Abacus *)getAdder { return [[Abacus alloc] init]; }
- (void)doWork {
Abacus *a = [self getAdder];
// Do lots of adding...
}
Then, in iOS 42, Apple comes up with a new innovation – the Calculator class! Your friends tell you that Calculator adds two numbers together more than twice as fast as Abacus, and all the cool kids are using it! You decide to refactor your code, but you realize that not only do you have to change the return type of getAdder, but also the types of all the variables to which you assign the return value of getAdder! Lame. What if you had done this instead:
- (id<Adder>)getAdder { return [[Abacus alloc] init]; }
- (void)doWork {
id<Adder> *a = [self getAdder];
// Do lots of adding...
}
Now, when you want to migrate to Calculator, you just need to change the body of getAdder to return [[Calculator alloc] init] and you're done! One line. The rest of your code stays exactly the same. In that case, you have hidden the true type of the instance returned from getAdder from the rest of your code. Information hiding makes refactoring easier.
Lastly, I promised to explain why something like Abacus <Adder> *a = ... is usually redundant. What you're saying here is "a is an instance of Abacus that conforms to Adder." But you (and the compiler) already know that Abacus conforms to Adder – it's right there in the interface declaration! As rmaddy points out, there are some cases where you want to talk about an instance that is either a given class, or a subclass thereof, and also specify that it conforms to a protocol, but those situations are rare, and most often specifying both a class and protocol conformance is unneeded.
For more information, check out Apple's Working with Protcols guide.
I'm implementing an application where both instances of a class as well as the class itself have "children" (placed inside a NSMutableArray). It's a pretty complicated application, but thanks to Objective-C, it's a breeze: classes are themselves objects and can have methods and "variables" (with the help of static variables and such).
To make it myself easy, I implemented accessor/setter method on both my instances (using -) and classes (using +) to fetch and manipulate the "children" without having direct access to the arrays. I like to have my objects as much as possible closed and the methods do some data validation.
I also implemented a fast enumeration instance method from the NSFastEnumeration protocol. And here comes the question: can I implement a fast enumeration class method and use it with Objective-C's for...in construct? In order words, can I implement this:
+ (NSUInteger)countByEnumeratingWithState: (NSFastEnumerationState *)state objects: (__unsafe_unretained id [])buffer count: (NSUInteger)len;
And then use it somewhere like that:
for (id child in [MyClass class]) {
// Do magic stuff…
}
I peeked in GNUStep's GSFastEnumeration.h file which implements fast enumeration as a macro, which affirms the above is possible, but I'm not sure if Apple does the same.
Even if I can't associate the NSFastEnumeration protocol to my class object, is fast enumeration without that protocol possible (and future-proof)?
The method -countByEnumeratingWithState:objects:count: is the whole of fast enumeration—the protocol is, I believe, mostly there for description (it's easier to implement a protocol than declare the method with the correct signature). I would expect it to work just fine, but I don't have a reference for that. You would probably want to loop over [MyClass class], though.
I would probably consider it future-proof. Note that it'd be really trivial to make a tiny wrapper class around your class object that does nothing but implement NSFastEnumeration and forward the instance method -countByEnumeratingWithState:objects:count: to your class's method +countByEnumeratingWithState:objects:count:.
I would recommend creating a protocol with a class method that is identical to the NSFastEnumeration method. You could then iterate over the [MyClass class] as John Calsbeek mentioned.
//Protocol implementation
#protocol FastClassEnumeration <NSObject>
#required
+ (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
#end
//Class implementation
#interface EnumeratedClass : NSObject<FastClassEnumeration>
#end
#implementation EnumeratedClass
+ (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len
{
static const unsigned long items_length = 4;
static NSString * items[items_length] = { #"item1", #"item2", #"item3", #"item4" };
if(state->state >= items_length)
{
return 0;
}
state->itemsPtr = items;
state->state = items_length;
state->mutationsPtr = (unsigned long *)self;
return items_length;
}
#end
//Usage
...
for(NSString *item in [EnumeratedClass class])
{
NSLog(#"%#", item);
}
...
can I ... ?
Well, did you try it? Does it work? If you've tried it, you would notice that it does indeed compile and work.
And why shouldn't it? Class objects are objects just like other objects. Class methods are just methods that happen to be on the class object. If you send a message to a class object, it will call a class method; whereas if you send a message to a non-class object, it will call an instance method. So pretty much, you can put class methods on a class and use the class object the same way you can use a normal object by putting instance methods on its class.
The only possible difference is that the class object won't explicitly conform to the NSFastEnumeration protocol, similar to if you loop over a normal object whose class does not explicitly specify that it conforms to the NSFastEnumeration protocol. So the question is, do they check that an object explicitly conforms to the protocol before using it (as opposed to checking if it responds to the selector)?
In my experience, for pretty much all of Cocoa, for APIs that say they require an object that conforms to a protocol, you can give an object that does not explicitly conform to the protocol, but implements all of the protocol's methods, and it will work fine. (How would they check it anyway? If they use conformsToProtocol:, that won't work for class objects since there's a +conformsToProtocol:, which has a different meaning. They would have to use runtime functions or special-case class objects probably.) For example, the NSDictionary documentation says its keys are required to conform to NSCopying, but if you have an object that does not conform to NSCopying, but does implement copyWithZone:, it works fine. (In fact, there is a +copyWithZone: method, whose stated purpose is to allow class objects to be used as dictionary keys, so obviously it is intended that keys don't need to explicitly conform to NSCopying.)
I've worked with a few different languages such as Java, C#, and Objective-C.
In most languages, methods that don't require an instance of an object are called static methods. However, when it comes to Objective-C, some people get defensive when you call them static methods, and they expect you to call them class methods.
Why are they called class methods instead of static methods? What is the difference between a static method and a class method?
So my question is why are they called class methods instead of a
static method? What is the difference between a static method and a
class method?
From Wikipedia: Static methods neither require an instance of the class nor can they implicitly access the data (or this, self, Me, etc.) of such an instance.
This describes exactly what Objective-C's class methods are not.
An Objective-C class method very much requires an instance that is the target of the method invocation. That is, it requires an instance of the metaclass that describes the class object being invoked.
Unlike static methods, Objective-C's class methods can be inherited (which, in combination with having the aforementioned self, is exactly why many classes can share a single, simple, implementation of +alloc on NSObject without needing their own custom implementations) and invoking a class method goes through the exact same objc_msgSend* based dispatch mechanism as any other method call site.
Objective-C's class methods can be overridden across the class hierarchy and they can be swizzled. None of which is supported in languages that typically offer static methods in lieu of class methods.
The bottom line is that static methods and class methods are very different. While that difference is mostly transparent for day to day coding purposes, there are still situations where knowing how class methods work can save you a ton of unnecessary lines of code.
For example, you can't do this with static methods:
#interface AbstractClass:NSObject
+ factory;
#end
#implementation AbstractClass
+ factory
{
return [[[self alloc] init] autorelease];
}
#end
#interface Concrete1:AbstractClass
#end
#implementation Concrete1
#end
#interface Concrete2:AbstractClass
#end
#implementation Concrete2
#end
void foo() {
Concrete1 *c = [Concrete1 factory];
Concrete2 *d = [Concrete2 factory];
... etc ...
}
Because it's dynamically bound, not static.
Because it's really a class object's instance method.
Objective-C class method is actually an object's class object's instance method.
It's hard to describe with text. See nice illustration here.
http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
Though class methods and static methods are in practice the same most of the time, they are different. With static methods the class is acting as a namespace qualifier. With class methods the class itself is an object and so class methods are to the class object exactly the same thing instance methods are to an instance; as a consequence you can do the following
#interface TestClass : NSObject
+ (void)classOrInstanceMethod;
- (void)classOrInstanceMethod;
#end
...
NSArray * arr = [NSArray arrayWithObjects:
[[[TestClass alloc] init] autorelease],
[TestClass class],
nil];
for( id obj in arr )
[obj classOrInstanceMethod];
which version of classOrInstanceMethod is called depends on whether obj is a class object or and instance. If you are familiar with the factory class pattern, this pattern is part of the Objective-C language.
This is purely a historical difference, mostly stemming from the fact that Objective-C was developed contemporaneously with C++, and before C++ or later languages like Java and C# had much influence. Objective-C was essentially a port of the Smalltalk object model to C, so its syntax and terminology don't necessarily seem as "C-like" as that used by C++. However, Objective-C was in no way bucking a trend by not using the term "static method", because that trend wasn't well-established back in 1983.
The top voted answer to this SA question ( Objective C Static Class Level variables ) outlines my question quite well but to it, I'd like to add one more criteria:
Issue Description
You want your ClassA to have a ClassB class variable.
You are using Objective-C as programming language.
Objective-C does not support class variables as C++ does.
I want to access ClassA's class variable from subclass ClassASub
or even better
4a. I want ClassA's method to access the class variable as it is, overridden in ClassASub
Any ideas? Or is this just bending Objective-C one step too far?
Just make a normal getter method for your class variable, and you can override it in the subclass. Just remember to access it through the method.
static SomeClass *gClassVar;
#implementation ClassA
+ (SomeClass *)classVar {
if (!gClassVar)
gClassVar = ...;
return gClassVar;
}
+ (...)someMethod {
[[self classVar] doSomething];
}
#end
Then,
static SomeClass *gClassVar;
#implementation ClassASubclass
+ (SomeClass *)classVar {
if (!gClassVar)
gClassVar = ...;
return gClassVar;
}
#end
So, when you call [ClassA someMethod], it will operate on the ClassA instance of classVar. When you call [ClassASubclass someMethod], it will operate on the ClassASubclass instance.
The idea of having variables of any sort attached to an object (class or instance) is a feature that is kind of "stapled on" to Objective C. Any time you want to do anything object-oriented using Objective C, start by working with methods. (Almost) everything else is just syntactic sugar for things you can do with methods.
The concept of private / protected / public is somewhat alien to Objective C, even though access control is supported for member variables. The best you can do for methods is to define them in a separate header (and this applies to class variables and properties, if we implement both using methods).
I am very, very new to Obj-C, and will have a ton of questions. (I have the book "iPhone Programming, The Big Nerd Ranch Guide", but it doesn't address the differences between C# and Obj-C. Does anyone know of a doc that does address the differences?).
Anyway, my question is above...
In Objective-C, object allocation and initialization are separate operations, but it's common and a good practice to see them called in the context of the same expression:
MyClass *myInstance = [[MyClass alloc] init];
// ...
[myInstance release];
In C#, allocation and initialization happen when you use new:
MyClass myInstance = new MyClass();
The runtime allocates the instance and then calls the constructor.
So yes, the C# constructor is equivalent to the Objective-C initializer, but the usage is different.
Apart from this ... init in Objective-C is just a normal instance method, without any special semantics. You can call it at any point. In C#, constructors are very special static-like methods treated differently by the runtime and with special rules. For example, the C# compiler enforces calls to the base class constructor.
They are similar only as much as you can compare two completely different methods for creating an object. Checkout this information on the Objective-C Runtime.
The following is a very simple (but hopefully not misleading) explanation:
Objective-C
id object = [MyObject alloc]; // allocates the memory and returns a pointer. Factory-like method from NSObject (unless your class overrides it)
MyObject *myObj = [object init]; // initializes the object by calling `-(id)init`. You'll want to override this, or a similar init method for all your classes.
Usually written like this:
MyObject *myObj = [[MyObject alloc] init];
From what I know, the C# constructor allocates the memory and calls the appropriate constructor function to initialize the object.
A difference is that in C# you can't call an inherited constructor (see the bottom of the link above) but in Obj-C this will compile, but will give you wrong results.
#interface ClassA : NSObject
- (id) initWithInteger:(int)num;
#end
#interface ClassB : ClassA
- (id) init;
#end
#implementation ClassB
- (id) init
{
self = [supere initWithInteger:10];
return self;
}
// main
ClassA *a = [[ClassA alloc] initWithInteger:10]; //valid
ClassB *a = [[ClassB alloc] initWithInteger:10]; // will call init from classA, bypassing and not calling init for classB.
Just be careful with weak/dynamic typed language of Objective-C
They're similar, but not identical. Technically, a constructor fully creates and initializes an instance, while an initializer takes an already constructed instance (usually gotten through alloc) and sets the instance up so that it's ready to be used.
As for the differences between Objective-C and C#: They're two different and mostly unrelated languages. When you're learning a new language, trying to think of it as "Like this language I already know, but with these differences" can actually make it harder to learn, because there are a lot of differences and they're often subtle, so going in with assumptions from another language will confuse you. If you search around Stack Overflow, you'll find a lot of PHP programmers who start to learn a new language and immediately wonder "How do I do variable variables in this language?" It's like looking for a list of the differences between English and Chinese — you're better off not trying to treat one like the other. Keep in mind what you already know, but try not to assume any of it is the same in Objective-C.