Superclass is an NSOperation class which implements NSXMLParserDelegate - all it does is sending URL request and parsing XML data returned from a server. This class is being inherited by a subclass which also implements NSXMLParserDelegate. The parent's parser delegate is supposed to catch general error from the XML response before passing it on to child's parser delegate to do more specific parsing.
Within the superclass:
#implementation Super
#pragma mark NSOperation method
- (void) main {
id parentDelegate = [self getParserDelegate]; //?
id childDelegate = [self getParserDelegate]; //??
}
// I would like this to return parser delegate in the super class
- (id) getParserDelegate {
return self;
}
#end
Within subclass:
#implementation Sub
// main is not overidden in subclass
// and this should return parser delegate in the sub class
- (id) getParserDelegate {
return self;
}
#end
I'm instantiating the operation using the child's class i.e. Sub
Sub *theSub = [[Sub alloc] init];
[self.queue addOperation:theSub]; // Super's main method will be called
Within Super's main method I would like to have access to both parent and child's delegate but I found that 'self' always resolves to Sub, regardless whether 'self' is called within Sub or Super. Is it possible to call Super's getParserDelegate from within Super's main or is it just a bad design?
self is a pointer directly to the object. So it resolves to the same thing no matter where you inspect it along the inheritance chain. There is no such thing as a self pointer that would resolve directly to the superclass — that's the difference between the 'is a' school of extending object functionality and 'has a'.
Any messages issued to self will always be sent first to the most junior child class, then work their way up per the usual inheritance rules. As a result there's absolutely nothing you can provide to NSXMLParser that would cause delegate methods to go straight in to the super class.
I'd suggest that what you're describing with a common actor that implements most of the logic and a separate actor that does twiddly specifics is itself the delegate pattern. So what you probably want is to turn what you currently have as a parent into its own sovereign class and attach what you currently have as the child to it as a delegate. Just reuse the NSXMLParserDelegate protocol for that delegation relationship if it makes sense.
Super class never know about what its child's, and what they do.
//in Super.h
- (id) getParserDelegate;
//in Super.m
- (id) getParserDelegate {
return self;
}
//in Child.h
- (id) getParserDelegate;
//in Child.m
- (id) getParserDelegate {
return [super getParserDelegate];
}
Related
#interface hello:SKScene
#end
#implementation hello
+(void)method{
[self here];
}
#end
main.m
[hello method];
here,when i call this class method without allocating memory for object then method self,belong to whom????
my question is self belong to class that contain the method calling on then because i did not define object then ,why i still can use self on this?????
is it still belong to class on which it calling ??please give me proper concept of self on instance method and class method.
When you refer to self in class method, self refers to the class, itself, not to a particular instance of that class. By using self rather than the actual class name in these class methods, it makes it easier to subclass the class in question. Specifically, the class method will be inherited, but the self references will now refer to the subclass rather than the base class. If you refered to the base class by name, this would not be true.
Consider this factory method:
#implementation BaseClassObject
// THIS IS WRONG
+ (BaseClassObject *)object {
return [[BaseClassObject alloc] init];
}
#end
And consider this subclass:
#interface SubClassObject : BaseClassObject
#end
Then consider code that does:
SubClassObject *object = [SubClassObject object]; // WRONG
The problem is that the object factory method will return a BaseClassObject rather than a SubClassObject. But that is remedied if we alter the definition of that factory class method to use self:
#implementation BaseClassObject
// THIS IS RIGHT
+ (instancetype)object {
return [[self alloc] init];
}
#end
Now when I refer to [SubClassObject object], I'll get an instance of SubClassObject rather than BaseClassObject.
Note: In my contrived example, it's rather important to use self. You may, though, encounter code where it does not appear to be immediately relevant (for example, you might have a base class, but no subclass at this time).
Even in this case, you probably should be in the habit of using self in these class methods, regardless, to "future-proof" your code, so that if you ever subclass this base class at some unforeseen date in the future, these class methods are more likely to function properly even when subclassed.
Just to add a little to Rob's answer: the class object is created automatically by the compiler and/or Objective-C runtime. (It doesn't matter to you which it is.) For all intents and purposes, it's permanent. There's no need for it to be managed.
Please consider the following code:
`#interface Parent : NSObject
- (void)whoAmI;
#end
#implementation Parent
- (void)whoAmI
{
NSLog(#"PARENT CALLED");
}
#end
#interface Child : Parent
- (void)test;
#end
#implementation Child
- (void)whoAmI
{
NSLog(#"CHILD CALLED");
}
- (void)test
{
NSLog(#"%#", [super class]);// CHILD!!!! why???
[super performSelector:#selector(whoAmI)];// "CHILD CALLED" why???
}
#end
`
When i call test method i expect to see parent class printed and parent whoAmI method executed. But surprisingly both times the derived class is called. Can anyone explain why it happens and how do i performSelector: on base class?
The super method is simply a way of forwarding a message to a superclass' implementation code. However, self remains the same. In fact, if you create an instance of Child, there is no instance of Parent at all. You can test this by NSLog-ing self as a %p to inspect the pointer address; when a super method is called, the self pointer is the same as it was for the instance of the subclass which called it:
Parent:
- (void)printAddr {
NSLog(#"%p", self);
}
Child:
- (void)printAddr {
NSLog(#"sub: %p, self");
[super printAddr];
}
You will see that the pointers are the same if you call [aChild printAddr];.
Now let's translate this into addressing your specific questions. First off, look at the performSelector: method. Its default implementation is in NSObject, and this implementation most likely uses self to call the selector. Because of this, even though the method implementation is that of NSObject, the method will still be called on the real object, your subclass. If it weren't for this behavior, performSelector: would always try to call the method as if it were implemented directly on NSObject unless you implemented your own performSelector: on a subclass; obviously, this is the wrong behavior.
In addition, the same thing holds true for the -class method. Its default implementation resides on NSObject, and obviously it would be boring id it always returned [NSObject class], so instead it effectively uses self to get the class of the real object.
You can also test what I've said here by making a method on the superclass which calls another method on self. Even if you use super to call the first method, the second method will still be called on your subclass since self still points to the subclass:
Parent:
- (void)method {
NSLog(#"Parent: method");
[self method1];
}
- (void)method1 {
NSLog(#"Parent method1");
}
Child:
- (void)method {
[super method];
}
- (void)method1 {
NSLog(#"Child: method1");
}
In this case, [aChild method] will output:
Parent: method
Child: method1
I have two classes, named Parent and Child, as below. Parent is the superclass of Child I can call a method of the superclass from its subclass by using the keyword super. Is it possible to call a method of subclass from its superclass?
Child.h
#import <Foundation/Foundation.h>
#import "Parent.h"
#interface Child : Parent {
}
- (void) methodOfChild;
#end
Child.m
#import "Child.h"
#implementation Child
- (void) methodOfChild {
NSLog(#"I'm child");
}
#end
Parent.h:
#import <Foundation/Foundation.h>
#interface Parent : NSObject {
}
- (void) methodOfParent;
#end
Parent.m:
#import "Parent.h"
#implementation Parent
- (void) methodOfParent {
//How to call Child's methodOfChild here?
}
#end
Import "Parent.h" in app delegate's .m file header.
App delegate's application:didFinishLaunchingWithOptions: method..
Parent *parent = [ [Parent alloc] init];
[parent methodOfParent];
[parent release];
You can, as Objective C method dispatch is all dynamic. Just call it with [self methodOfChild], which will probably generate a compiler warning (which you can silence by casting self to id).
But, for the love of goodness, don't do it. Parents are supposed to provide for their children, not the children for their parents. A parent knowing about a sub-classes new methods is a huge design issue, creating a strong coupling the wrong way up the inheritance chain. If the parent needs it, why isn't it a method on the parent?
Technically you can do it. But I suggest you to alter your design. You can declare a protocol and make your child class adopt that protocol. Then you can have to check whether the child adopts that protocol from the super class and call the method from the super class.
You could use this:
Parent.m
#import "Parent.h"
#implementation Parent
- (void) methodOfChild {
// this should be override by child classes
NSAssert(NO, #"This is an abstract method and should be overridden");
}
#end
The parent knows about the child and child has a choice on how to implement the function.
super means "invoke a method dispatching on the parent class", so can use super in the subclass because a subclass only has one parent class. A class can have many _sub_classes though, so how would you know which method implementation to call, in the general case? (Hence there is no such thing as a sub keyword.)
However, in your example you have two separate methods. There's nothing stopping you (assuming you have very good reasons for doing something like this!) from saying, in the parent,
- (void) methodOfParent {
[self methodOfChild];
}
if your super has multiple subs then go for this one for the specific
sub's method
if ([super isKindOfClass:[specificsub class]]) {
[specificsub methodName];
}
if your super is dealing with that object (that sub) so sub's method
loggedin will be called an other way is in you super class
super *some = [[sub alloc] init];
[some methodName];
This can be done by over riding the method in subclass. That is create a method in parent class and over ride the same in subclass.
Does calling [super init] do the same thing in a category as a subclass? If not, what's the difference?
In order to understand this, it's probably important to understand the way an object is stored during runtime. There is a class object1, which holds all the method implementations, and separately, there is a structure with the storage for the instance's variables. All instances of a class share the one class object.
When you call a method on an instance, the compiler turns that into a call to objc_msgSend; the method implementation is looked up in the class object, and then run with the instance as an argument.
A reference to super takes effect at compile time, not run time. When you write [super someMethod], the compiler turns that into a call to objc_msgSendSuper instead of the usual objc_msgSend. This starts looking for the method implementation in the superclass's class object, rather than the instance's class object.2
A category simply adds methods to the class object; it has little or no relation to subclassing.
Given all that, if you refer to super inside of a category, it does indeed do the same thing that it would inside of a class -- the method implementation is looked up on the class object of the superclass, and then run with that instance as an argument.
Itai's post answers the question more directly, but in code:
#interface Sooper : NSObject {}
- (void) meth;
#end
#interface Sooper ()
- (void) catMeth;
#end
#interface Subb : Sooper {}
- (void) subbMeth;
#end
#interface Subb ()
- (void) catSubbMeth;
#end
#implementation Sooper
- (void) meth {
[super doIt]; // Looks up doIt in NSObject class object
}
- (void) catMeth {
[super doIt]; // Looks up doIt in NSObject class object
}
#end
#implementation Subb
- (void) subbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
- (void) catSubbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
#end
1 See Greg Parker's writeup [objc explain]: Classes and meta-classes
2One important thing to note is that the method doesn't get called on an instance of the superclass. This is where that separation of methods and data comes in. The method still gets called on the same instance in which [super someMethod] was written, i.e., an instance of the subclass, using that instance's data; it just uses the superclass's implementation of the method.
So a call to [super class] goes to the superclass object, finds the implementation of the method named class, and calls it on the instance, transforming it into the equivalent of [self theSuperclassImplementationOfTheMethodNamedClass]. Since all that method does is return the class of the instance on which it was called, you don't get the superclass's class, you get the class of self. Due to that, calling class is kind of a poor test of this phenomenon.
This whole answer completely ignores the message-passing/method call distinction. This is an important feature of ObjC, but I think that it would probably just muddy an already awkward explanation.
No, they do different things. Imagine a class structure like this: NSObject => MyObject => MySubclass, and say you have a category on MyObject called MyCategory.
Now, calling from MyCategory is akin to calling from MyObject, and therefore super points to NSObject, and calling [super init] invokes NSObject's -init method. However, calling from the subclass, super points to MyObject, so initializing using super invokes MyObject's -init method, which, unless it isn't overridden, behaves differently from NSObject's.
These two behaviors are different, so be careful when initializing using categories; categories are not subclasses, but rather additions to the current class.
Given the below example, super will call UIView init (not UINavigationBar init method)
#implementation UINavigationBar (ShadowBar)
- (void)drawRect:(CGRect)rect {
//draw the shadow ui nav bar
[super init];
}
#end
If you subclass it, [super init] will call UINavigationBar init method.
So yes, if there are additional things you will do in UINavigationBar init (extra from UIView) they do different things.
Edit: the following is built on a flawed premise, please look at josh's answer.
not deleting, still an interesting reference for something that could potentially lead you astray.
They are the same thing... without referencing any outside dicussions we may have had where you stated that I should ..."answer an academic question with an academic answer"
#implementation categoryTestViewController (ShadowBar)
- (void)viewDidAppear:(BOOL)animated {
//draw the shadow ui nav bar
NSLog(#"super's class = %#, self's class %#",[super class],[self class]);
if ([self class] == [super class]) {
NSLog(#"yeah they are the same");
}
}
#end
outputs:
2011-05-29 08:06:16.198 categoryTest[9833:207] super's class = categoryTestViewController, self's class categoryTestViewController
2011-05-29 08:06:16.201 categoryTest[9833:207] yeah they are the same
and calling the [super viewDidAppear:] will result in calling nothing... not a loop, so I don't know what it is really doing there.
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.