Suppose I have an object "dog" of class "Dog" whose properties can be divided into two groups:
(A) properties that must be initialized only once, when dog is allocated;
(B) properties that must be re-initialized (reset) every once in a while;
So I need a method "resetB" which resets properties in group (B) using self, i.e.
-(void) resetB {
self.propB1 = initValB1;
self.propB2 = initValB2;
self.propB3 = initValB3;
}
In order to avoid duplicated code (the actual situation is much more complicated, with tens of properties) I'd like to call "resetB" from my "init", so that init wuold look like this
-(id) init {
self = [super init];
if ( self ) {
propA1 = initValA1;
propA2 = initValA2;
propA3 = initValA3;
[self resetB];
}
return self;
}
Ok, but now I'm worried that I'm messaging "self" from my "init" method, which people say is considered... "impolite"... (so to speak).
My questions are: do I worry too much about etiquette, and it is actually safe to do as above? Or, maybe, duplicate code (which must be kept in sync) is the lesser evil? Or there is another "correct" way of doing this?
Sending a message to self from init is safe when two conditions are met:
the method you are calling is not overridden by a derived class -- in which case the derived class implementation would be called before the object is fully initialised;
you are not setting a property, which could trigger some action on the same object (which would still be non-fully initialised) through KVO.
If your reset method (non associated to setting properties) is meant to be private, there should no problem with it, unless someone defines a method with the same name in a derived class.
To reduce this risk further, you can use a naming convention for your private methods e.g., _resetB.
I believe the only reason it's considered potentially dangerous to call methods on self from within init is when you are calling a property setter or another method where KVO could cause side-effects.
If you know that method won't cause side-effects then it's safe to call, and it's pretty normal to call a common "setup method" from multiple versions of init or from awakeFromNib etc.
EDIT As mentioned by #sergio another reason to avoid calling a method on self from init is that it could be overridden by a subclass which is not properly initialised. One way around that is to put the reset implementation into a private method, which is called from init and have the public method use the private method also. While the private method could also be overridden, it should be obvious that it shouldn't have been:
#interface MyClass ()
- (void)_resetB;
#end
#implementation MyClass
-(id) init {
self = [super init];
if ( self ) {
_propA1 = initValA1;
_propA2 = initValA2;
_propA3 = initValA3;
[self _resetB];
}
return self;
}
- (void)resetB
{
[self _resetB];
}
#pragma mark - Private Methods
- (void)_resetB
{
_propB1 = initValB1;
_propB2 = initValB2;
_propB3 = initValB3;
}
#end
I want to create a class cluster with a base class and 2 subclasses. Creating an instance of the base class should return a subclass based on some conditions, but creating a subclass directly should create it. I wrote the following code in the base class:
+ (id)allocWithZone:(NSZone *)zone {
// prevent infinite recursion
if ([self isEqual:Base.class]) {
// if self is the base class, return a correct subclass
if (somecondition) {
return [SubclassA alloc];
}
return [SubclassB alloc];
}
// otherwise, alloc is called on a subclass
// call NSObject's alloc
return [super allocWithZone:zone];
}
and it works, but I'm really surprised that it does. Namely, when invoked on a subclass, why does super evaluate to the Base class's superclass (NSObject), and not the Base class (because invoked on SubclassA, the superclass is Base)? It is as if the allocWithZone: method call, inherited from Base, just always evaluated super relative to Base, not the real runtime class of the caller. I think similar code in Java and other OO languages would not work and result in infinite recursion, would it? Is this code wrong?
Your code is correct. [super ...] always uses the superclass of the class implementing the method. In your code, +allocWithZone: is implemented by class Base, so [super allocWithZone:zone] uses Base's superclass when searching for the next +allocWithZone: implementation to call.
If self is able to store the base class instance then when we are returning the self, how it transformed to derived instance.
Here's what I think you're asking: suppose we have a base class Base and a subclass Derived. If -[Derived init] calls -[Base init] and -[Base init] returns a different instance, won't that different instance be an instance of Base and not Derived and thus inappropriate? For example, the new object won't have the instance variables that Derived might have added to the class.
The answer is that Base is not allowed to do that. If it replaces the original instance, it must do so in a manner that respects the dynamic type of that original instance. For example, it might do something like:
// Re-allocate with 100 extra bytes
id newSelf = NSAllocateObject([self class], 100, [self zone]);
[self release];
self = newSelf;
// ... continue to initialize ...
return self;
Or, it might dynamically generate a new subclass of the original class and then allocate a new instance of that new class.
NSString* newClassName = [NSString stringWithFormat:"%#_DynamicSubclass", NSStringFromClass([self class])];
Class newClass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);
// ... further configure the new class, by adding instance variables or methods ...
objc_registerClassPair(newClass);
id newSelf = [newClass alloc];
[self release];
self = newSelf;
// ... continue to initialize ...
return self;
Whatever it does, it has to satisfy the constraint that the new instance is suitable to be used wherever the old instance was, based on its dynamic type.
self is a hidden method argument:
// this Objective-C
- (id) initWithString:(NSString*)str;
// gets implemented like this C function would be
- (objc_object*) Foo_initWithString(Foo* self, SEL _cmd, NSString* str);
It is a pointer to memory (allocated with alloc) that is already big enough to hold the most derived object. The most derived class calls super's init, which also calls its super's init and so each class in hierarchy gets its constructor called.
So, nothing is transformed — it is just a pointer to an already existing object, you can either return it (99.9% of the time) or substitute another object instead.
Note there is a second hidden argument, the selector _cmd, which in this case equals to #selector(initWithString:). You can also use it if you need current method name e.g. for debug logging.
Here super instance is not assigned to derived instance. self = [super init]; is simply like telling the runtime system to look for the init method to the super class method selector table... inside super -init method, the self is like support for both super class and derived class. In objective c, incase of class inheritance.. only instance variables are duplicated.. methods are shared by all classes in hierarchy. If u override.. u should do self = [super init]; this will lead u to NSObject -init method. If we override -init... methods from super class, make sure that the super -init... is called first. This is what i understand. Thank you.
What's the difference between a class method and an instance method?
Are instance methods the accessors (getters and setters) while class methods are pretty much everything else?
Like most of the other answers have said, instance methods use an instance of a class, whereas a class method can be used with just the class name. In Objective-C they are defined thusly:
#interface MyClass : NSObject
+ (void)aClassMethod;
- (void)anInstanceMethod;
#end
They could then be used like so:
[MyClass aClassMethod];
MyClass *object = [[MyClass alloc] init];
[object anInstanceMethod];
Some real world examples of class methods are the convenience methods on many Foundation classes like NSString's +stringWithFormat: or NSArray's +arrayWithArray:. An instance method would be NSArray's -count method.
All the technical details have been nicely covered in the other answers. I just want to share a simple analogy that I think nicely illustrates the difference between a class and an instance:
A class is like the blueprint of a house: You only have one blueprint and (usually) you can't do that much with the blueprint alone.
An instance (or an object) is the actual house that you build based on the blueprint: You can build lots of houses from the same blueprint. You can then paint the walls a different color in each of the houses, just as you can independently change the properties of each instance of a class without affecting the other instances.
Like the other answers have said, instance methods operate on an object and has access to its instance variables, while a class method operates on a class as a whole and has no access to a particular instance's variables (unless you pass the instance in as a parameter).
A good example of an class method is a counter-type method, which returns the total number of instances of a class. Class methods start with a +, while instance ones start with an -.
For example:
static int numberOfPeople = 0;
#interface MNPerson : NSObject {
int age; //instance variable
}
+ (int)population; //class method. Returns how many people have been made.
- (id)init; //instance. Constructs object, increments numberOfPeople by one.
- (int)age; //instance. returns the person age
#end
#implementation MNPerson
- (id)init{
if (self = [super init]){
numberOfPeople++;
age = 0;
}
return self;
}
+ (int)population{
return numberOfPeople;
}
- (int)age{
return age;
}
#end
main.m:
MNPerson *micmoo = [[MNPerson alloc] init];
MNPerson *jon = [[MNPerson alloc] init];
NSLog(#"Age: %d",[micmoo age]);
NSLog(#"%Number Of people: %d",[MNPerson population]);
Output:
Age: 0
Number Of people: 2
Another example is if you have a method that you want the user to be able to call, sometimes its good to make that a class method. For example, if you have a class called MathFunctions, you can do this:
+ (int)square:(int)num{
return num * num;
}
So then the user would call:
[MathFunctions square:34];
without ever having to instantiate the class!
You can also use class functions for returning autoreleased objects, like NSArray's
+ (NSArray *)arrayWithObject:(id)object
That takes an object, puts it in an array, and returns an autoreleased version of the array that doesn't have to be memory managed, great for temperorary arrays and what not.
I hope you now understand when and/or why you should use class methods!!
An instance method applies to an instance of the class (i.e. an object) whereas a class method applies to the class itself.
In C# a class method is marked static. Methods and properties not marked static are instance methods.
class Foo {
public static void ClassMethod() { ... }
public void InstanceMethod() { ... }
}
The answer to your question is not specific to objective-c, however in different languages, Class methods may be called static methods.
The difference between class methods and instance methods are
Class methods
Operate on Class variables (they can not access instance variables)
Do not require an object to be instantiated to be applied
Sometimes can be a code smell (some people who are new to OOP use as a crutch to do Structured Programming in an OO enviroment)
Instance methods
Operate on instances variables and class variables
Must have an instanciated object to operate on
I think the best way to understand this is to look at alloc and init. It was this explanation that allowed me to understand the differences.
Class Method
A class method is applied to the class as a whole. If you check the alloc method, that's a class method denoted by the + before the method declaration. It's a class method because it is applied to the class to make a specific instance of that class.
Instance Method
You use an instance method to modify a specific instance of a class that is unique to that instance, rather than to the class as a whole. init for example (denoted with a - before the method declaration), is an instance method because you are normally modifying the properties of that class after it has been created with alloc.
Example
NSString *myString = [NSString alloc];
You are calling the class method alloc in order to generate an instance of that class. Notice how the receiver of the message is a class.
[myString initWithFormat:#"Hope this answer helps someone"];
You are modifying the instance of NSString called myString by setting some properties on that instance. Notice how the receiver of the message is an instance (object of class NSString).
Class methods are usually used to create instances of that class
For example, [NSString stringWithFormat:#"SomeParameter"]; returns an NSString instance with the parameter that is sent to it. Hence, because it is a Class method that returns an object of its type, it is also called a convenience method.
So if I understand it correctly.
A class method does not need you to allocate instance of that object to use / process it. A class method is self contained and can operate without any dependence of the state of any object of that class. A class method is expected to allocate memory for all its own work and deallocate when done, since no instance of that class will be able to free any memory allocated in previous calls to the class method.
A instance method is just the opposite. You cannot call it unless you allocate a instance of that class. Its like a normal class that has a constructor and can have a destructor (that cleans up all the allocated memory).
In most probability (unless you are writing a reusable library, you should not need a class variable.
Instances methods operate on instances of classes (ie, "objects"). Class methods are associated with classes (most languages use the keyword static for these guys).
Take for example a game where lots of cars are spawned.. each belongs to the class CCar.
When a car is instantiated, it makes a call to
[CCar registerCar:self]
So the CCar class, can make a list of every CCar instantiated.
Let's say the user finishes a level, and wants to remove all cars... you could either:
1- Go through a list of every CCar you created manually, and do whicheverCar.remove();
or
2- Add a removeAllCars method to CCar, which will do that for you when you call [CCar removeAllCars]. I.e. allCars[n].remove();
Or for example, you allow the user to specify a default font size for the whole app, which is loaded and saved at startup.
Without the class method, you might have to do something like
fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();
With the class method, you could get away with [FontHandler getDefaultFontSize].
As for your removeVowels function, you'll find that languages like C# actually have both with certain methods such as toLower or toUpper.
e.g. myString.removeVowels() and String.removeVowels(myString) (in ObjC that would be [String removeVowels:myString]).
In this case the instance likely calls the class method, so both are available.
i.e.
public function toLower():String{
return String.toLower();
}
public static function toLower( String inString):String{
//do stuff to string..
return newString;
}
basically, myString.toLower() calls [String toLower:ownValue]
There's no definitive answer, but if you feel like shoving a class method in would improve your code, give it a shot, and bear in mind that a class method will only let you use other class methods/variables.
class methods
are methods which are declared as static. The method can be called without creating an instance of the class. Class methods can only operate on class members and not on instance members as class methods are unaware of instance members. Instance methods of the class can also not be called from within a class method unless they are being called on an instance of that class.
Instance methods
on the other hand require an instance of the class to exist before they can be called, so an instance of a class needs to be created by using the new keyword. Instance methods operate on specific instances of classes. Instance methods are not declared as static.
In Objective-C all methods start with either a "-" or "+" character.
Example:
#interface MyClass : NSObject
// instance method
- (void) instanceMethod;
+ (void) classMethod;
#end
The "+" and "-" characters specify whether a method is a class method or an instance method respectively.
The difference would be clear if we call these methods. Here the methods are declared in MyClass.
instance method require an instance of the class:
MyClass* myClass = [[MyClass alloc] init];
[myClass instanceMethod];
Inside MyClass other methods can call instance methods of MyClass using self:
-(void) someMethod
{
[self instanceMethod];
}
But, class methods must be called on the class itself:
[MyClass classMethod];
Or:
MyClass* myClass = [[MyClass alloc] init];
[myClass class] classMethod];
This won't work:
// Error
[myClass classMethod];
// Error
[self classMethod];
CLASS METHODS
A class method typically either creates a new instance of the class or retrieves some global properties of the class. Class methods do not operate on an instance or have any access to instance variable.
INSTANCE METHODS
An instance method operates on a particular instance of the class. For example, the accessors method that you implemented are all instance methods. You use them to set or get the instance variables of a particular object.
INVOKE
To invoke an instance method, you send the message to an instance of the class.
To invoke a class method, you send the message to the class directly.
Source: IOS - Objective-C - Class Methods And Instance Methods
Class methods can't change or know the value of any instance variable. That should be the criteria for knowing if an instance method can be a class method.
Also remember, the same idea applies to variables. You will come across terms like static, member, instance, class and so on when talking about variables the same as you would for methods/functions.
It seems the common term in the Obj-C community is ivar for instance variable, but I am not an Obj-C guy, yet.
An update to the above answers, I agree instance methods use an instance of a class, whereas a class method can be used with just the class name.
There is NO more any difference between instance method & class method after automatic reference counting came to existence in Objective-C.
For Example[NS StringWithformat:..] a class method & [[NSString alloc] initwihtformat:..] an instance method, both are same after ARC
Note: This is only in pseudo code format
Class method
Almost does all it needs to do is during compile time. It doesn't need any user input, nor the computation of it is based on an instance. Everything about it is based on the class/blueprint——which is unique ie you don't have multiple blueprints for one class. Can you have different variations during compile time? No, therefore the class is unique and so no matter how many times you call a class method the pointer pointing to it would be the same.
PlanetOfLiving: return #"Earth" // No matter how many times you run this method...nothing changes.
Instance Method
On the contrary instance method happens during runtime, since it is only then that you have created an instance of something which could vary upon every instantiation.
initWithName: #"John" lastName: #"Doe"Age:12 #"cool"
initWithName: #"Donald" lastName: #"Drumpf"Age:5 attitude:#"He started"
initWithName: #"President" lastName: #"Obama"Age:54 attitude: #"Awesome"
//As you can see the value can change for each instance.
If you are coming from other languages Static methods are same as class methods.
If you are coming from Swift, type methods are same as class methods.
Adding to above answers
Class method will work on class, we will use this for general purpose where like +stringWithFormat, size of class and most importantly for init etc
NSString *str = [NSString stringWithFormat:#"%.02f%%",someFloat];
Instance Method will work on an instance of a class not on a class like we are having two persons and we want to get know the balance of each separately here we need to use instance method. Because it won't return general response. e.g. like determine the count of NSSArray etc.
[johnson getAccountBalance];
[ankit getAccountBalance];
I'm new to Objective C and I haven't been able to find out if there is the equivalent of a static constructor in the language, that is a static method in a class that will automatically be called before the first instance of such class is instantiated. Or do I need to call the Initialization code myself?
Thanks
The +initialize method is called automatically the first time a class is used, before any class methods are used or instances are created. You should never call +initialize yourself.
I also wanted to pass along a tidbit I learned that can bite you down the road: +initialize is inherited by subclasses, and is also called for each subclasses that doesn't implement an +initialize of their own. This can be especially problematic if you naively implement singleton initialization in +initialize. The solution is to check the type of the class variable like so:
+ (void) initialize {
if (self == [MyParentClass class]) {
// Once-only initializion
}
// Initialization for this class and any subclasses
}
All classes that descend from NSObject have both +class and -class methods that return the Class object. Since there is only one Class object for each class, we do want to test equality with the == operator. You can use this to filter what should happen only once ever, versus once for each distinct class in a hierarchy (which may not yet exist) below a given class.
On a tangential topic, it's worth learning about the following related methods, if you haven't already:
- isMemberOfClass:(Class)aClass (true only for aClass itself)
- isKindOfClass:(Class)aClass (true for aClass and children)
+ isSubclassOfClass:(Class)aClass (same as above, but a class method)
Edit: Check out this post by #bbum that explains more about +initialize: https://web.archive.org/web/20201108095221/http://www.friday.com/bbum/2009/09/06/iniailize-can-be-executed-multiple-times-load-not-so-much/
Also, Mike Ash wrote a nice detailed Friday Q&A about the +initialize and +load methods:
https://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html
There is the +initialize class method that will be called before a class is used.
A bit of an addendum to this topic:
There is another way to create a 'static constructor' in obj-c, using an __attribute directive:
// prototype
void myStaticInitMethod(void);
__attribute__((constructor))
void myStaticInitMethod()
{
// code here will be called as soon as the binary is loaded into memory
// before any other code has a chance to call +initialize.
// useful for a situation where you have a struct that must be
// initialized before any calls are made to the class,
// as they would be used as parameters to the constructors.
// e.g.
myStructDef.myVariable1 = "some C string";
myStructDef.myFlag1 = TRUE;
// so when the user calls the code [MyClass createClassFromStruct:myStructDef],
// myStructDef is not junk values.
}