问题
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?
回答1:
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.
回答2:
For your example:
- Subclass
UIImageto, 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];
回答3:
The approach that solved my problem was to use a category instead of inheritance (credits go to Jonathan Cichon in the comments of my question). I used Associative References to declare and store additional data in the category implementation as discussed a lot here in SO. I would like to drive the attention to the NSObject category implementation proposed by Jonathan that makes really easy and elegant to add associative references to any object.
来源:https://stackoverflow.com/questions/17144701/objective-c-class-inheritance-with-factory-methods