Hi all.
I am writing an application in Objective-C (using the Cocoa frameworks.) At one point, I needed to come up with a technique to allow a class to be extended in the future without affecting any other classes that reference it. The requirements are:
Ok, by no means are these requirements completely written in stone, but they are just a way for me to convey what I'm trying to do.
So, what I did works, but I have a feeling there is probably a better way. How I did it is this:
Here is my lib.h:
This works great. And throughout the rest of the application, all I'd need to do to use a method from the selected class is use the MyClass macro defined above like this:
As good as it works, I'm not a huge fan of having to use a Macro masquerading as a class name. I am wondering if there is a way to maybe use a factory class to give me the correct class name. Something like:
Or maybe have each of the classes compiled into it's own external library and then choose which library file to use via the project compilation options. Though not sure if this is possible or how to begin approaching this.
Anyone have any suggestions?
Thanks in advance!
I am writing an application in Objective-C (using the Cocoa frameworks.) At one point, I needed to come up with a technique to allow a class to be extended in the future without affecting any other classes that reference it. The requirements are:
- The class (herein referred to as ClassA) will only have class methods, and cannot be instantiated.
- Define a protocol that ClassA adopts, and in which future derived classes or completely new replacements classes must adopt.
- Need the ability for me or others (as painlessly as possible) to either provide a new derived class using ClassA as a base, or a completely new replacement class not derived from ClassA, but which adopts the protocol.
- Need a way for the owner of the project (me, in this case) to (at any time) select either ClassA or any of the future derived or replacement classes, as the class to use in the application. This selection is done at compile-time, not at run-time, via twiddling some #define somewhere or what not.
- The other classes used throughout the project that use the selected class should not need to be modified in any way, or be concerned about which version it is using.
Ok, by no means are these requirements completely written in stone, but they are just a way for me to convey what I'm trying to do.
So, what I did works, but I have a feeling there is probably a better way. How I did it is this:
- I created a protocol defining the class methods that are required and put it in it's own .h file.
- I created the ClassA class which adopts the protocol and defined all the required class methods.
- As a test I created a new class called ClassB which inherits from ClassA and defines only the class methods that it wants to replace.
- As another test, I created yet another class called AlternateClass which inherits from NSObject and adopts the protocol. It defines all of the required classes.
- Finally, and this is the key, I created a .h file (mylib.h) that contains nothing but some pre-processor macros that #defines some symbols representing the different classes in existence and an #if to import the required file and define which class is being used.
Here is my lib.h:
Code:
//Define the libraries.
#define MY_CLASSA_LIB 1
#define MY_CLASSB_LIB 2
#define ALT_CLASS_LIB 3
// Twiddle this value to select a library to use.
#define LIB_TO_USE ALT_CLASS_LIB
#if LIB_TO_USE == MY_CLASSA_LIB
#import "ClassA.h"
#define MyClass ClassA
#elif LIB_TO_USE == MY_CLASSB_LIB
#import "ClassB.h"
#define MyClass ClassB
#elif LIB_TO_USE == ALT_CLASS_LIB
#import "AltClass.h"
#define MyClass AltClass
// Add new elif sections here for other future classes.
#endif
This works great. And throughout the rest of the application, all I'd need to do to use a method from the selected class is use the MyClass macro defined above like this:
Code:
[MyClass callMethod1];
As good as it works, I'm not a huge fan of having to use a Macro masquerading as a class name. I am wondering if there is a way to maybe use a factory class to give me the correct class name. Something like:
Code:
// Remember, the class only contains class methods,
// so a factory class that returns an object won't work here.
class MyClass = [MyLib theChosenClass]; // Not a valid Obj-C statement.
[MyClass callMethod1];
Or maybe have each of the classes compiled into it's own external library and then choose which library file to use via the project compilation options. Though not sure if this is possible or how to begin approaching this.
Anyone have any suggestions?
Thanks in advance!
Last edited: