Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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..

like image 384
Hwee-Boon Yar Avatar asked Oct 14 '22 03:10

Hwee-Boon Yar


2 Answers

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

like image 164
Jano González Avatar answered Oct 18 '22 21:10

Jano González


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.

like image 43
Barry Wark Avatar answered Oct 18 '22 19:10

Barry Wark