Calling child overrided method from parent - objective-c

I'm having trouble finding out the way to implenent something similar to abstract class in Objective-C.
I don't actually care about restricting to use my base class without subclassing it, all I want is this:
I want to have class A (parent/base/abstract) which has method something like - (void)makeRequest and I want to subclass it in classes B,C,D etc and have methods like - (id)getCachedResult that are being called from class' A method. So basically I want class A to implement some base logic and I want it's subclasses to modify some details and parts of this base logic.
Sounds like a trivia, but I can't put my finger on the way to implement such pattern in Objective-C.
UPDATE:
Here's what I'm trying to do:
#interface A : NSObject
- (void)makeRequest;
- (NSString *)resultKey;
#property (strong) NSMutableDictionary * result;
#end
#implementation A
- (void)makeRequest
{
self.result[self.resultKey] = #"Result";
}
- (NSString *)resultKey
{
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"%# should be overrided in subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
return nil;
}
#end
/////////////////////////////
#interface B : A
#end
#implementation B
- (NSString *)resultKey
{
return #"key";
}
#end
When I'm creating instance of class B and trying to call it's method - (void)makeRequest I'm getting exception, and that's pretty obvious. What I want is a way to correctly design my classes for the same purpose.

As requested: You should declare resultKey in B's interface. :-)

Related

Inheritance in class methods

I have the following class:
#interface ClassA
+ (void)method1;
+ (void)method2;
#end
#implementation ClassA
+ (void)method2 {
[self method1];
}
#end
And one that inherits from it:
#interface ClassB : ClassA
#end
#implementation ClassB
+ (void)method1 {
NSLog(#"ClassB");
}
#end
If in an specific segment of code I do:
[ClassB method2];
It will throw an error cause it will try to call [ClassA method1], but this class doesn't implement that method. Is it even possible somehow that call is make to ClassB and not to ClassA? Scenario is: I have a base class with some utility class methods that relate in between them. Children don't need to implement those, but need to implement one that is used inside some of those methods. But once the flow goes into the parent, when it calls this method, it calls the parent one - which is not implemented.
You have multiple problems:
First
First point deleted thanks to #rmaddy comments.
Second
Your methods return a instancetype variable, while they don't: if you want to leave your implementation like that, change your method to return void
Third
You forgot implementation of + (instancetype)method1; so this code it not valid.

How to initialize a subclass of PFObject?

So I'm trying to clean up my code and move all of one object's logic to it's own class.
I want to be able to do something like this:
#interface Habit : PFObject<PFSubclassing>
and then be able to call
[Habit calculateStreak].
How would I initialize Habit with an already created PFObject and all of its data? Something like [Habit * running = Habit initWithThis:someObjectWithData]? Or am I thinking of this all wrong?
Subclassing is pretty easy: Just inherit from PFObject and adopt the PFSubclassing protocol:
#interface Habit : PFObject <PFSubclassing>
- (id)calculateStreak;
#end
Then, make sure you override the parseClassName to return the Parse class name:
#implementation Habit
- (NSString *)parseClassName
{
return #"Habit";
}
#end
You also have to register your subclass, which should be done in +[Habit load]:
#implementation Habit
- (void)load
{
[self registerSubclass];
}
- (NSString *)parseClassName
{
return #"Habit";
}
#end
Then you can instantiate the class the way you would any other Parse class, using +[object] or the like:
Habit *habit = [Habit object];

Sending message from super class to subclass

I have a base class lets say BaseClass which does some logic and handles gestures. I have another class FooBarClass which provides the view and is also a subclass of BaseClass, (FooBar : Base).
I know that I can call methods in super class by super methodName. I am stuck in a situation now, all of views are designed like these and now I need to pass message from FooBar to Base.
Is that possible ? If so how ? Should I be using NSNotifications or is there any better way to do it ?
If you are creating instance of subclass, which in your case is FooBarClass, you need not worry about message passing from super class to subclass. With inheritance, whatever properties, methods are exposed in header file (.h) of BaseClass, can be accessed from FooBarClass. If the methods belonging to BaseClass has been overridden in FooBarClass, then you have to explicitly make use of super otherwise, you can directly call self. However, if the properties belonging to BaseClass has been overridden in FooBarClass, then that variable will be holding the value which has been stored last. That is the reason why usually, properties are never overridden as it gets confusing.
Lastly, there is no need for NSNotification.
Ex: BaseClass.h
#interface BaseClass : UIView
- (void)runTest;
- (void)sayHi;
- (void)sayHi2;
#property (assign, nonatomic) NSInteger commonVar;
#end
BaseClass.m
- (void)runTest
{
self.commonVar = 100;
}
- (void)sayHi
{
NSLog(#"Hi from super");
NSLog(#"In super variable = %d", self.commonVar);
}
- (void)sayHi2
{
NSLog(#"Hi from super2");
}
FooBarClass.h
#interface FooBaseClass : BaseClass
#property (assign, nonatomic) NSInteger commonVar;
#end
FooBarClass.m
- (void)runTest
{
self.commonVar = 1;
[super runTest]; // Now, commonVar variable will be holding 100 throughout.
[super sayHi];
[super sayHi2]; // Same as next line because there is no sayHi2 overridden.
[self sayHi2];
[self sayHi];
}
- (void)sayHi
{
NSLog(#"Hi from derived");
NSLog(#"In derived variable = %d", self.commonVar);
}
Hope this answer helps you.

Is it possible to add a category to an Objective-C meta-class?

I would assume... NO. But wouldn't it be nice if instead of...
NSStringFromClass(SomeClass)
you could...
#interface Class (ToString)
#property (readonly) NSString* stringValue;
#end
#implementation Class (ToString)
- (NSString*) stringValue { return NSStringFromClass(self); }
#end
and subsequently use...
SomeClass.stringValue
I'm sure there's a good reason the meta-heirarchy prevents this (although it seems like a half-truth when it's said that Classes (and Protocols, and Methods, etc) are-indeed "real" Objects)... when a lot of the "stuff" that makes a NSObject an Object can NOT be performed on a "metaclass".
Can anyone shed a light on this functional difference / offer an alternative (i.e. resolveClassMethod: that might achieve similar result?
Since an instance method of a metaclass is just a class method on the non-meta class, why not simply add a category on the original (non-meta) class?
#implementation NSObject (Name)
+ (NSString *)className
{
return NSStringFromClass(self);
}
#end

Objective-C inheritance; calling overridden method from superclass?

I have an Objective-C class that has a method that is meant to be overridden, which is uses in a different method. Something like this:
#interface BaseClass
- (id)overrideMe;
- (void)doAwesomeThings;
#end
#implementation BaseClass
- (id)overrideMe {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
- (void)doAwesomeThings {
id stuff = [self overrideMe];
/* do stuff */
}
#end
#interface SubClass : BaseClass
#end
#implementation SubClass
- (id)overrideMe {
/* Actually do things */
return <something>;
}
#end
However, when I create a SubClass and try to use it, it still calls overrideMe on the BaseClass and crashes due to doesNotRecognizeSelector:. (I'm not doing a [super overrideMe] or anything stupid like that).
Is there a way to get BaseClass to call the overridden overrideMe?
What you are describing here should work so your problem is likely elsewhere but we don't have enough information to help diagnose it.
From your description, I'd say either the instance you're messaging is not the class you think it is or you made some typo in your code when declaring the method names.
Run your application under gdb, add a symbolic breakpoint on objc_exception_throw, reproduce your problem. Once your process has stopped on the "doesNotRecognizeSelector" exception, print object description and it's class.
Or log it before calling -overrideMe:
NSLog(#"object: %# class: %#", obj, [obj class])
Write a category for BaseClass to override the method.
#interface BaseClass (MyCategory)
- (id) overrideMe;
#end
#implementation BaseClass (MyCategory)
- (id) overrideMe
{
/* Actually do things */
return <something>;
}
#end
Now all instances of BaseClass will respond to selector overrideMe with the new implementation.