How to call method in same class - objective-c

I have a superclass, SuperClassYeh and a subclass, SubClassYeh. I have method inheritTest in SuperClassYeh and I override inheritTest in SubClassYeh. I start the program running by calling method testSuperAndSelf in SubClassYeh. This method would call another method, fromYEH in SuperClassYeh. In fromYEH, I would like to call inheritTest in SuperClassYeh. How do I do that? Using [self inheritTest] calls the inheritTest in SubClassYeh, not SuperClassYeh.
Here's the code fragment to start the whole thing running
SubClassYeh *testing = [[SubClassYeh alloc] init];
[testing testSuperAndSelf];
Here's the code fragment for SuperClassYeh
- (void) fromYEH
{
[self inheritTest]; //Calls the inheritTest in SubClassYeh, not SuperClassYeh
}
- (void) inheritTest
{
NSLog(#"Testing Indicator. Inside SuperClassYEH inheritTest");
}
Here's the code fragment for SubClassYeh
- (void) inheritTest
{
NSLog(#"Testing Indicator. Inside SubClassYeh inheritTest");
}
- (void) testSuperAndSelf
{
[super fromYEH];
}

You can't, and this is the intended behaviour of inheritance in Objective-C.
If self is an instance of SubClassYeh, then
[self inheritTest]
calls the SubClassYeh implementation of inheritTest (if there is one),
no matter from where that message is sent (subclass or superclass).
The only difference between [super fromYEH] and [self fromYEH] is that the lookup
for the "fromYEH" message starts at the superclass, but it does not change the fact
that self is an instance of SubClassYeh.
And you cannot prevent a method from being overriden in Objective-C
(see How to avoid superclass methods getting overridden by sub class in objective - c or other Q&A's about that topic).
The only thing that you can do in the superclass is to choose method names
that are not overriden accidentally, e.g. by prefixing the method name
with the class name, as suggested here: https://stackoverflow.com/a/17209309/1187415.

If you can call [super fromYEH] from SubClassYeh, what is the problem in calling [super inheritTest] the same way?

Even it is a quite strange behavior, you can try something like this(didn't test it, actually)
- (void) fromYEH
{
bool isSubClass = [self isKindOfClass:[SubClassYeh class]];
if(isSubClass == YES)
{
[super performSelector:#selector(inheritTest)];
}
else
{
[self inheritTest];
}
}
Anyway, even if this code will really do the trick, I still think that this is very bad practice.
EDIT:
Checked this in XCode. It will not do the trick =) So upvoted Martin's answer =)

I found the solution. Instead of calling [super fromYeh]in testSuperAndSelf, change the receiver to the superclass. Use [[[[SubClassYeh superclass] alloc] init] fromYEH]. Inside method fromYEH, the inheritTest of SuperClassYEH would be called.
Here is the code fragment for method testSuperAndSelf in SubClassYeh. Other codes remain the same.
- (void) testSuperAndSelf
{
[[[[SubClassYeh superclass] alloc] init] fromYEH];
}

Just for the record...
What you want to do isn't as difficult as you think, if you look at it from a different perspective.
All you have to do is define a C function and call that.
- (void) fromYEH
{
inheritTest(self); //Calls the inheritTest() in SuperClassYeh
}
void inheritTest(SuperClassYeh *self)
{
NSLog(#"Testing Indicator. Inside SuperClassYEH inheritTest");
}
- (void) inheritTest
{
inheritTest(self);
}
(I love the names... ;)

Related

ObjC: using "super" in conjunction with overriding

I have a class A and a class B which is a subclass of A. Both have the following methods:
-(void)anotherMethod{
// implementation of A or B
}
-(void)aMethod{
#try{
[super aMethod];
}
#catch(NSException *e){
}
[self anotherMethod];
}
Now: if I call [instanceOfClassB aMethod] the instruction [self anotherMethod] contained in A's implementation of aMethod calls B's anotherMethod (since it's overridden) instead of A's one. How can I make A's implementation of aMethod call A's implementation of anotherMethod?
Try this:
if ([self isKindOfClass:[ClassB class]]) {
[super anotherMethod];
} else {
[self anotherMethod];
}
This should help you out:
This person had the same problem as yours.
Objective-c: Calling [self message] on a base class is invoking the descendant method
The solution is doing a method swizzling before (and immediately after) calling super in order to replace the subclass implementation with the superclass one. It requires "hacking" the runtime, that's right, but I haven't found anything simpler than this. And it works.

Preventing subclasses overriding methods

Assume there is an object that initialises like so
- (void)doInit
{
NSLog(#"In BaseClass init");
}
- (id)init
{
self = [super init];
[self doInit];
return self;
}
and it has a subclass which is inited in a similar way
- (void)doInit
{
NSLog (#"In SubClass init");
}
- (id)init
{
self = [super init];
[self doInit];
return self;
}
Now if I create an instance of child class then I receive the following output:
In SubClass init
In SubClass init
when really, what I meant to happen is
In BaseClass init
In SubClass init
Is there a way to mark doInit to say that it shouldn't be overridden or do I need to create a unique name for all methods in a subclass?
I'm not entirely sure how I haven't come across this issue before, but there you go.
Edit:
I understand why this is happening, I hadn't expected that the base class would be able to call the overridden function.
I also can't just call [super doInit]; from the Subclass method because the BaseClass still needs to call doInit so that creating an instance of BaseClass will still work. If I called [super doInit], I'd still end up getting SubClass's doInit called twice.
It appears the answer is no and I'll just have to uniquely name each doInit like doBaseClassInit and doSubClassInit.
If you have a method that you don't want to by dynamically bound (i.e. don't want a subclass method to be called if it exists), you need to do it as a C function instead. So, you could do this instead:
In the base class:
static void DoInit(BaseClass *self)
{
NSLog(#"In BaseClass init");
}
- (id)init
{
self = [super init];
if (self) {
DoInit(self);
}
return self;
}
in the subclass:
static void DoInit(SubClass *self)
{
NSLog(#"In SubClass init");
}
- (id)init
{
self = [super init];
if (self) {
DoInit(self);
}
return self;
}
Note that both the DoInit methods are marked as static, so they are only visible each compilation unit (.m file) and don't conflict with each other.
You could, perhaps, try something like this in your base class. It would mean any time the init implementation inside BaseClass executed, the doInit implementation for BaseClass would be called.
- (void)doInit
{
NSLog(#"In BaseClass init");
}
- (id)init
{
self = [super init];
Class baseClass = [BaseClass class];
SEL selector = #selector(doInit);
IMP baseClassImplementation = class_getInstanceMethod(baseClass, selector);
baseClassImplementation(self, selector);
return self;
}
As I mentioned in my comment, if that's the narrowness of your need this should work as it gets around the dynamic method lookup involved with sending a message. Hope this helps!
EDIT:
Disclaimer - if you're in this situation it's probably not a good sign for the longevity of your design. This technique will get you up and running for now but please document it carefully, and consider ways to refactor your code so this is no longer used. Consider fixes like these to really be used only when extremely urgent.
The reason why you are not getting the "In BaseClass init" console message is because your subclass is not calling the super's implementation of doInit.
If you don't want doInit overridden the 'best' way to avoid doing so is to not publish the existence of this method. Remove it from your header and uniquely name the method so that a collision is unlikely. For example, many of the private methods in Apple's frameworks have a leading underscore. So, for example, you could call your method _doInit and it will be very unlikely that a subclass accidentally create it's own overiding implementation.
Nope, there's no enforceable way to prevent a subclass from overriding a method. The best you can do is to avoid putting it in the public header file for the class so someone is not likely to try to override it. If the method has to be public, you just put a note in the documentation for the method that it shouldn't be overridden or that subclasses should call super's implementation whichever the case may be. You'll find these kind of instructions all over in the documentation for Apple's own classes.
If you want your subclass to use the baseclass version of doInit then in the subclass don't declare a doInit method. Here's what I mean:
ClassA:
#interface ClassA :
-(void) doInit;
-(id) init;
#implementation
-(void) doInit {
NSLog(#"ClassA doInit");
}
-(id) init {
self = [super init];
if (self != NULL)
[self doInit];
return self;
}
ClassB
#interface ClassB : ClassA
-(id) init;
#implementation
-(id) init {
self = [super init];
if (self != NULL)
[self doInit];
return self;
}
And really you don't need to override the init method as well unless there's some special code that you want that class to do.

objective c help - calling methods?

Hey,
I am new to programming I wanted to know why is it always [self method];? I mean why is it that way could someone explain me why is it self and what is going on in the background? sorry if it is a stupid question
thanks,
TC
Basically, what self refers to is the object that you're currently in the context of. [self somemethod] means that you're invoking a method named somemethod in the class that self was initialized as.
For example, if you were to do something like this:
Foo *f = [[Foo alloc]init];
[f someMethod];
You'd be invoking someMethod on the Foo instance.
But if you're working inside of the class Foo, self serves as an explicit reference to the current object. In this case, you'd simply use [self someMethod] to invoke someMethod.
-(id) init {
if (self = [super init]) {
[self someMethod];
}
...
}
-(void) someMethod { }
Does that help?
[self method] calls the method of the calling class. For example, in the header file of your class,
#interface YourClass : NSObject {
}
- (void) myMethod;
then, you can call the 'myMethod' in YourClass by using [self myMethod]. Does it make sense?
During calling [self method], there is no any background working. [self method] is almost same the calling function in C. When you use [self method], 'method' in your class is just called right away.
Because [self method]; calls the -method method in the class from which it is called.
If you want kill John in ObjC:
[john sendBullet]
if you do sendBullet to myself (shortly self), it's a suicide
[self sendBullet]
got the difference? :)

Simple inheritance question in Objective-C

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.

Is this valid code to create a NIB-instantiated singleton?

Assume that I instantiate an object of class MyGreatClass in my NIB (as usual by simply dragging an "Object" to the NIB and settings its class to MyGreatClass).
I want access to that instance anywhere in my codebase, without introducing coupling, i.e. without passing objects around like crazy, and without having an outlet to it in, say, [NSApp delegate]. (The latter would make AppDelegate terribly bulky with time.)
I ask: Is the following considered a good code to accomplish this?
//imports
static MyGreatClass *theInstance = nil;
#implementation MyGreatClass
+ (MyGreatClass *)sharedInstance
{
NSAssert(theInstance != nil, #"instance should have been loaded from NIB");
return theInstance;
}
- (id)init //waking up from NIB will call this
{
if (!theInstance)
theInstance = self;
return theInstance;
}
// ...
If this work as expected, I would after the app is loaded be able to access my instance via sharedInstance.
What do you think?
UPDATE: Hmm, on the second thought, the above init method maybe overkill. This is way simpler to think about:
- (id)init
{
NSAssert(!theInstance, #"instance shouldn't exist yet because only "
#"the NIB-awaking process should call this method");
theInstance = self;
return theInstance;
}
Again, what do you think?
The proper way to create a singleton is to override allocWithZone: to ensure another object cannot be created. Overriding init allows the new object to be created, but not initialized. It is thrown away because the init method simply ignores it and returns the object that has been created already. Here is how I would do it:
+ (MyGreatClass *)sharedInstance {
NSAssert(theInstance != nil, #"instance should have been created from NIB");
return theInstance;
}
+ (MyGreatClass *)allocWithZone:(NSZone *)zone {
if(theInstance) return theInstance;
return [[self alloc] init];
}
- (id)init {
if(theInstance) return theInstance;
if(self = [super init]) {
theInstance = self;
// other initialization
}
return self;
}
- (void)release {}
- (void)dealloc {
return;
[super dealloc]; // Prevent compiler from issuing warning for not calling super
}
I overrode release and dealloc to ensure that the singleton would not be deallocated. If you don't do this, you should retain and autorelease it in the sharedInstance method. If you want to support multithreading, you should also synchronize access to the theInstance variable.