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.
Related
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.
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. :-)
I have an interesting problem where I am trying to call class methods on an class which I essentially know nothing about in my test method. I can inspect its inheritance and any protocols it may implement but can't see an easy way to just call a method on it without getting tied up with an NSInvocation. The code below, albeit crudely, tries to demonstrate the problem I am having.
#interface ClassA : NSObject
+ (Class)classIsPartialClassOf;
#end
#implementation ClassA
+ (Class)classIsPartialClassOf {
return [NSString class];
}
#end
#interface ClassB : NSObject
#end
#implementation ClassB
- (id)init {
[ClassB testClass:[ClassA class]];
}
+ (void)testClass:(Class)classDecl {
/* obviously if you know the type you can just call the method */
[ClassA classIsPartialClassOf];
/* but in my instance I do not know the type, obviously there are no classmethods to perform selector such as the fictional one below */
[classDecl performSelector:#selector(classIsPartialClassOf)];
}
#end
Methods for getting implementations seem to return instance variants and I can't get them to fire on the static class itself.
Are my options limited to invocations or have I missed something obvious and should kick myself?
Thank you in advance for your help.
What is the problem? Your code
[classDecl performSelector:#selector(classIsPartialClassOf)];
should work. As will (simpler to write)
[classDecl classIsPartialClassOf];
Class objects are objects. And class methods are simply methods called on a class object.
"Methods for getting implementations seem to return instance variants and I can't get them to fire on the static class itself."
Then use objc_getMetaClass("ClassName") instead of objc_getClass. Class objects are objects themselves and are instances of their metaclass. If you pass the metaclass object to e. g. class_getMethod(), everything will be fine.
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.
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.