Question

I'm just trying to learn objectives-c.

I've seen wikipedia example for AbstractFactory pattern, across different languages.

Here's the Button definition:

@protocol Button
- (void)paint;
@end

@interface WinButton : NSObject <Button>
@end

Here's a factory:

@implementation WinFactory
- (id)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end

As far as I kwnow, obj-c's id keyword should be something like C#'s var or C++11's auto, right?

So I my question is:

why let the factory return a generic object of a not specified type? Is this an error (that let factory return something other that is not a Button) or is there any reason to do that?

I'd write a factory this way:

@implementation WinFactory
- (id<Button>)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end 

am I wrong?

Was it helpful?

Solution

why let the factory return a generic object of a not specified type?

In many cases where you see id returned, it is because they are not consistently typed (really abstract objects), or it is because an implicit upcast would have been introduced.

Is this an error (that let factory return something other that is not a Button) or is there any reason to do that?

It is not an error. Of course, you should not return a type which does not match.

I'd write a factory this way:… am I wrong?

@implementation WinFactory
- (id<Button>)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end

The big gotcha in this scenario is that ObjC is quite loosely typed, and you should strive to ensure all selectors' parameters and return types match. That is to say, every createButton in all your translations should all return the same type and have the same types for parameters. Sometimes you will have to choose a more descriptive name in order to avoid ambiguity for the compiler.

That ought to explain why +[NSString string] returns id -- if it returned NSString, then +[NSMutableString string] could be a source of warnings. This is because the compiler can have a difficult (impossible) time matching a method declaration to a dynamic instance. That may also help you understand the 'wordy' naming of selectors, such as convenience constructors which also contain the type in the method (e.g. +[NSDictionary dictionaryWithObject:] as opposed to simply +[NSDictionary withObject:]).

But to get to your question: id<Button> or NSObject<Button>* or some other qualified type is just fine -- as long as you can live with that common method signature. You're introducing type-qualification, which helps the compiler help you.

OTHER TIPS

The more correct return type here would be :

- (id<Button>)createButton;

This means that the returned type is an object that conforms to the <Button> protocol. I may fix up the WP page just to be a little more clear. The <Button> protocol should also inherit from the <NSObject> protocol for completeness (and to simplify actual usage).

Note that the Abstract Factory pattern is somewhat unusual in ObjC. I'm trying to think of a case where it's used in UIKit or Foundation. It's more common for the class to handle this internally (such as in NSNumber) and is called a class cluster.

Be very careful of trying to code in a C++ or C# style in ObjC. ObjC is not a static language, and the patterns used are often quite different. (I'm not saying that AF is a static pattern. It could be used quite well in ObjC. I'm just saying that the fact that you're looking at it while trying to learn ObjC means that you may be approaching it backwards, learning "how do I do this C++ in ObjC" rather than learning "how do I develop in ObjC.")

Objective-C has the concept of class clusters, which are abstract factories. See this answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top