Sharing common method implementation between classes implementing the same protocol in Objective C - objective-c

I have a protocol.
MyProtocol.h:
#protocol MyProtocol
#property(nonatomic, retain) NSString* someString;
- (void)doesSomethingWithSomeString;
#end
And 2 classes that implement the same protocol. For some reason the 2 classes cannot inherit from the same base class. E.g. 1 of them might need to inherit from NSManagedObject (Core Data class in Apple's Cocoa framework) while the other shouldn't.
Class1.h:
#interface Class1: NSObject<MyProtocol> {
NSString* someString;
}
//Some method declarations
#end
Class1.m
#implementation Class1
#synthesize someString;
- (void)doesSomethingWithSomeString {
//don't use property here to focus on topic
return [[self someString] capitalizedString];
}
//Method definitions for methods declared in Class1
#end
Class2.h:
#interface Class2: SomeOtherClass<MyProtocol> {
NSString* someString;
}
//Some method declarations
#end
Class2.m
#implementation Class2
#synthesize someString;
// This is exactly the same as -doesSomethingWithSomeString in Class1.
- (void)doesSomethingWithSomeString {
//don't use property here to focus on topic
return [[self someString] capitalizedString];
}
//Method definitions for methods declared in Class2
#end
How can I avoid the duplication of -doesSomethingWithSomeString? (I guess I need something like categories for multiple classes).
Update:
There has been some suggestions of a helper class and delegating calls from Class1 and Class2 to it. It might be a good approach generally, especially if the methods are long.
In this case, I am looking at Class1 inheriting from NSObject and Class2 inheriting from NSManagedObject. The latter being a base class that Class2 has to subclass from, as a model/entity within the Apple Core Data framework.
So while delegation to a third class is one way to do this, there needs to be a lot of boilerplate delegation wrapper code for what amounts to many short 1-2 methods in the 3rd class. i.e. high boilerplate delegation code to actual code ration.
Another point is, as this is a model class, the common code mostly acts on ivars/properties, the delegation class will end up written almost like global C functions..

You can create a helper class an then use it from Class1 and Class2, and then only the call to the method on the helper class will be duplicated

This situation indicates that your Class1 and Class2 are not fully factored into classes that handle just one concern. The fact that you have a common implementation indicates that there should be a third class that provides that implementation and to which Class1 and Class2 can delegate that concern. In other words, this is a case for composition instead of inheritance.
Update
If it doesn't make sense to delegate to a class, don't forget that Objective-C is a superset of C. There's nothing stoping you from implementing a library of C functions that you can call from both classes to encapsulate the common behavior. If you're committed to conveniences like NSAssert et al., you can always implement them as class methods on a utility class or category on NSObject.

Personally I think this should be duplicated. You will likely need to customise one of them eventually and then you will be annoyed at all the work you did to prevent the duplication. Anything large can go into categories on the objects you are working with similar to whats going on inside capitalizedString.

Related

Category on NSObject also works on Class

So I have a category on NSObject called CustomCategory, as following:
#import <Foundation/Foundation.h>
#interface NSObject (CustomCategory)
-(BOOL)doSomething;
#end
#import "NSObject+CustomCategory.h"
#implementation NSObject (CustomCategory)
-(BOOL)doSomething
{
NSLog(#"Done");
return NO;
}
#end
Ideally, this will work on an object like this:
NSObject* object = [NSObject new];
[object doSomething];
However, I found that it also works in this way with no problem:
[NSObject doSomething];
So I am wondering, since it is an instance method I have added through the category, why it also works on a Class?
Instance methods on NSObject are also class methods on NSObject.
This works because of the way Objective-C does dynamic dispatch. If you send a message to any object the method implementation is looked up in the objects class. If you send a message to a class then you are sending a regular message to the class object. There the implementation is looked up in the so called meta-class. The meta-classes are automatically generated by the compiler. Class methods are just instance methods of the meta-class. This is handled transparently by the compiler.
Inheritance also works on the meta-class level. So the meta-class for a class inherits from the meta-class of its superclass. We have two parallel inheritance hierarchies there. Only root classes like NSObject are handled differently. There the meta-class can't inherit from the meta-class of the superclass as there is no superclass. For root classes the meta-class inherits from the root class itself.
And since class methods of a class are instance methods of its meta-class and NSObjects meta-class inherits from NSObject itself instance methods on NSObject are also class methods on NSObject.
For reference to anyone looking for the actual location of this in the runtime source, it currently resides in objc-runtime-new.mm's methodizeClass function:
... snip...
// Root classes get bonus method implementations if they don't have
// them already. These apply before category replacements.
if (cls->isRootMetaclass()) {
// root metaclass
addMethod(cls, SEL_initialize, (IMP)&objc_noop_imp, "", NO);
}
... snip ...
... And the +initialize method of a meta-class will add all of the method implementations from its instance and convert them into a class method.
And, contrary to what #Sven has been saying, NSObject's meta-class is not actually NSObject. A class always has a separate meta-class in the runtime, regardless of whether it is root or not.
Every Class in Objective C is internally an object, which means it's a subclass of NSObject.

Advice in Objective-C OOP Design

I have a class A with methods update & updatedMessage:(BOOL) isMatched points:(int) points.
Now I was thinking of creating at least 3 subclass, with different implementation on a particular method. However inside this implemented method on the subclass I still need to call
instance methods implemented from the superclass and update an instance variable. So I am calling these methods using:
[super updateMessage];
[super.flippedCards addObject:newObj];
Is there a better approach? Is this approach okay? Any disadvantage?
Thank you.
Unless those methods are overridden in your child class and you specifically want to call the super class's implementation of those methods, you can just call them on yourself:
[self updateMessage];
[self.flippedCards addObject:newObj];
If you want to create sub class to have different implementation on method, I think you can create a protocol with that method
#protocol DoSomethingProtocol
- NSString* Update:(NSString *message);
Create 3 class that conform this protocol and implement the method that you want it differently in these class
#interface WorkerA<DoSomethingProtocol>
#interface WorkerB<DoSomethingProtocol>
#interface WorkerC<DoSomethingProtocol>
And in your class A, declare
#property(nonatomic, assign) id<DoSomethingProtocol> worker;
If you want this class do something like WorkerA could do, just assign it with a Worker A or B
- (id)initWithStrategy:(id<DoSomethingProtocol>) strategy{
// super init
worker = strategy;
}
and in your class A
self.message = [worker Update:self.message];
[self.flippedCards addObject:newObj];
so you can easy choose what the worker should do and can update instance variable in your class without calling it in children class.
This is delegate pattern in Objective-C and similar with Strategy Pattern in .NET

Calling a static method in an unknown type of class

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.

Does Objective-C have something like C++ virtual functions?

In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?

Category usage in Objective-C

I'm seeing some code I've inherited that looks like the following:
#interface SomeClass (private)
This is within SomeClass.m, the implementation file. There is an accompanying header file which doesn't suggest that the class is using a category. Is (private) in this case just a poor name given to a category for SomeClass? And I'm assuming it's perfectly legitimate to specify categories such as these in an implementation?
It isn't the name "private" that makes it private; the methods are private because they are in a category declared within the implementation file.
There are three uses of a category, each of which add methods to a class (note: methods only, not iVars)
Extending an existing Cocoa class
This lets you add your own methods to an existing class.
For example, if you want to extend NSString to apply special capitalization, you could create a new class called, say NSString+Capitals. in the NSString+Capitals.h you would have:
#interface NSString (Capitals)
-(NSString *)alternateCaps:(NSString *)aString;
#end
and in NSString+Capitals.m you would implement the method
#implementation NSString (Capitals)
-(NSString *)alternateCaps:(NSString *)aString
{
// Implementation
}
Private methods on a class
This is the same as above, except that the extra methods are declared and defined in the implementation file (.m) Usually a way of having private methods - because they are not in the .h file (which is the one #imported by other classes) they are simply not visible. In this case, the implementation of the methods are done in their own implementation block. e.g
// someClass.m
#interface someClass (extension)
-(void)extend;
#end
#implementation someClass
// all the methods declared in the .h file and any superclass
// overrides in this block
#end
#implementation someClass (extension)
-(void)extend {
// implement private method here;
}
Class Extension (New for 10.5 Leopard)
A simpler way of having private methods. In this special case, the category name is empty and the private methods are implemented in the same block as all the other class methods.
// someClass.m
#interface someClass ()
-(void)extend;
#end
#implementation someClass
// all the methods declared in the .h file and any superclass
// overrides in this block
// Implement private methods in this block as well.
-(void)extend {
// implement private method here;
}
#end
Here's a link to the Apple docs on Categories and extensions.
"Private" is just a name that suggests the methods are not public and are used for the internal implementation of the class, but there's nothing in the declaration of the category that enforces that.
Also, methods defined in a category are added to the class definition at runtime, so the accompanying header file need not declare that it is using a category -- it gets "used" automatically.
I use that to give me somewhere to declare (and thus document, as well as shut the compiler up about) helper methods which don't need to be in the public interface. Then the "consumers" of the class are (tacitly, given that there's nothing stopping them other than good manners) restricted to using methods defined in the header file.