In Objective-C, how do I call an object's super class method?
For example, lets say I have an instance of an object "foo".
"foo" has a method that is overriden. I do not want to call this overriden method. Instead, I want to call the original method on the foo object instance.
You cannot do:
[[instance super] super_method]; as far as I am aware. So how can I go about doing this?
I know I can add a method to foo:
-(void) callsuper
{
[super super_method];
}
and do:
[foo callsuper];
Any other ways? I really don't want to create a method just to do that.
The keyword super does this for you. It is seen very commonly in -init methods. Here is an example.
- (id)init {
if (self = [super init]) {
// custom initialization
}
return self;
}
In this case, the super keyword is used to call this class' superclass implementation of the -init method. super can be used on any method that your superclass implements.
Related
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.
Say I have a class named Item. Which is a superclass of NewsItem and TwitterItem.
If I want to create some NewsItem's do I have to use (inside constructor)
self = [super init];
If yes, why? In Java/C# I would just do,
NewsItem n = new NewsItem();
I don't have to do anything with superclasses in Java/C#. Just can't grasp it.
In Java and C#, the compiler automatically makes your constructor call the superclass constructor if you don't explicitly call it. For example, the “Java Tutorials” say this:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
In Objective-C, the compiler doesn't do it automatically, so you have to do it yourself.
Because your superclass (and your superclass's superclass) need a chance to initialize, too.
And, keep in mind, that your superclass will [rarely] return nil or a different instance.
Which is why you do:
- (id)init
{
self = [super init];
if (self) {
... init stuff ....
}
return self;
}
Because you are overriding the init message. If you don't override it then [[NewsItem alloc] init] would just call the superclass' init message. In C#, you might use base to do the same.
since your custom object will at least inherit from the mothers of all Objects: NSObject, you have to call '[super init];'
'super' simply does call the init Method of its superclass
I have a class Foo that implements an +(void)initialize method. I also have a class that's a subclass of Foo. When I instantiate the subclass, the initialize method also gets called on Foo which I don't want. How do I prevent this?
Thanks.
In your scenario (when there are subclasses involved) you should check the class to which the initialize method is sent:
+ (void) initialize
{
if ( self == [MyClass class] )
{
// Do something here only once
}
}
You'll need to implement + (void)initialize in your subclass as well. Usually people call [super initialize], but you'll want to skip that step. An empty method will prevent Foo's from being called.
EDIT The superclasses initialize method is always called. It can't and shouldn't be prevented by subclassing, because technically the superclass is initialized too and could be used independently.
I've solved it by not implementing initialize and just calling a setup method instead
I have two Objective-C classes and one is derived from the other as
#interface DerivedClass : BaseClass
{
}
The code section below belongs to BaseClass:
- (id)init {
if (self = [super init]) {
[self configure];
}
return self;
}
- (void) configure{} //this is an empty method
And the code section belongs to the DerivedClass:
-(void) configure{
NSLog(#"derived configure called");
}
Now, when I say derivedInstance = [DerivedClass new]; and watch the call stack, I see that the configure method of my derived class gets called at the [self configure] line of the base's init method.
I'm an Objective-C noob and I'm confused about how a method of a derived class gets called from the method of a base class. "self" keyword is explained to be the same thing as "this" keyword of some languages but I think this explanation is not completely correct, right?
[self someMessage] will send the message "someMessage" to the current object, which is an instance of DerivedClass.
Message dispatch is done dynamically at run-time, so it will behave as whatever the object is at that time.
- (id) init
{
[super init];
//initialitation of the class
return self;
}
I know that when I am inheriting from another class I am suppose to call super.init
Does this apply to "inheriting from NSObject" ?
Yes, usually you have something like:
- (id) init
{
if (self = [super init]) {
// instantiation code
}
return self;
}
Technically, yes, because Apple's documentation says init... methods should always include a call to super. However at present, the NSObject implementation of -init does nothing, so omitting the call wouldn't prevent your code from working.
The downside of omitting the call to super is that your code wouldn't be as robust to future changes; for example if you later changed the inheritance, or if (God forbid) Apple changed NSObject's -init method so that it actually did something essential.