Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C class inheritance with factory methods

I would like to inherit from a framework class that has a factory method. How can I make the factory method return an object of my inherited class type? I found this useful article which describe a similar situation but in their case you have control over the superclass. How could I write, say, a subclass of UIImage that imageNamed: would return an object of my subclass type?

like image 503
MrTJ Avatar asked Jun 17 '13 09:06

MrTJ


People also ask

What is inheritance in Objective-C?

“ A key idea in all object-oriented programming, is inheritance that a new class can base itself on an existing class. It's another form of code reuse.

Is multiple inheritance possible in Objective-C?

In keeping with its clean and simple design, Objective C does not support multiple inheritance, though features have been developed to replace some of the functionality provided by multiple inheritance (see run-time section below). The root of the Objective C class hierarchy is the Object class.

What is @implementation in Objective-C?

As noted, the @implementation section contains the actual code for the methods you declared in the @interface section. You have to specify what type of data is to be stored in the objects of this class. That is, you have to describe the data that members of the class will contain.

What are methods in Objective-C?

Basically in Objective-C, we call the function as method. The Objective-C foundation framework provides numerous built-in methods that your program can call. For example, method appendString() to append string to another string.


2 Answers

I would like to inherit from a framework class that has a factory method. How can I make the factory method return an object of my inherited class type?

This is all you should have to do:

@interface MONImage : UIImage
@end

@implementation MONImage
@end

Then:

MONImage * image = [MONImage imageNamed:name];

How could I write, say, a subclass of UIImage that imageNamed: would return an object of my subclass type?

+[UIImage imageNamed:]'s implementation wrote subclassers out of this approach. Consequently, you would need to implement this method yourself.

Here's how one should declare a factory method:

+ (instancetype)imageNamed:(NSString *)pName;

and how one should implement it:

+ (instancetype)imageNamed:(NSString *)pName
{
  MONImage * image = [[self alloc] initWithThisDesignatedInitializer:pName];
                       ^^^^ NOTE: self, not a concrete class
  ...set up image...
  return image;
}

but they did not do it that way -- +[UIImage imageNamed:] wrote subclasses out and returns a UIImage when you write MONImage * img = [MONImage imageNamed:pName];. Sometimes that is done for a good reason. Some methods should have 'final' semantics. This often appears when your method may return multiple types, as in a class cluster. The language does not express 'final' methods -- but such a method should at least be documented.


So to come around to this UIImage case:

@interface MONImage : UIImage

+ (instancetype)imageNamed:(NSString *)pName;

@end

@implementation MONImage

+ (instancetype)imageNamed:(NSString *)pName
{
    UIImage * source = [UIImage imageNamed:pName];
    CGImageRef cgImage = source.CGImage;
    if (cgImage)
        return [[self alloc] initWithCGImage:cgImage];
    // try it another way
    return nil;
}

@end

Note that UIImages and CGImages are immutable. This should not result result in a deep copy of the image data.

like image 166
justin Avatar answered Oct 25 '22 19:10

justin


For your example:

  • Subclass UIImage to, say, MyImage
  • Implement the imageNamed: method to do anything specific that you need to be done.
  • Call that method on that class: MyImage *newImage = [MyImage imageNamed:imageName];
like image 36
Abizern Avatar answered Oct 25 '22 21:10

Abizern