patternMinor
How could this constructor code be improved?
Viewed 0 times
thisimprovedcouldconstructorhowcode
Problem
How could this constructor code be improved? I feel like I'm not doing something optimally here...
id or JGProduct return type?
I see a lot of people writing
instead - why is this?
Surely any subclass of JGProduct would be exchangeable for the superclass... Or should I be returning something that is
JGProduct or [self class] in initialiser?
I also see this:
or
Why would someone write either of these? The top one surely would not make the right kind of object if ran by a subclass. And what's the difference between
Thanks for any feedback!
@interface JGProduct : NSObject {
NSString *identifier;
}
+(JGProduct *)productWithIdentifier:(NSString *)identifier_;
-(JGProduct *)initWithIdentifier:(NSString *)identifier_;
@end
@implementation JGProduct
+(JGProduct *)productWithIdentifier:(NSString *)identifier_ {
return [[[[self class] alloc] initWithIdentifier:identifier_] autorelease];
}
-(JGProduct *)initWithIdentifier:(NSString *)identifier_ {
self = [super init];
if (self) {
_identifier = [identifier_ retain];
}
return self;
}
@endid or JGProduct return type?
I see a lot of people writing
-(id)initWithIdentifier:(NSString *)identifier_ {instead - why is this?
Surely any subclass of JGProduct would be exchangeable for the superclass... Or should I be returning something that is
id but conforms to a protocol (if present)?JGProduct or [self class] in initialiser?
I also see this:
+(JGProduct *)productWithIdentifier:(NSString *)identifier_ {
return [[[JGProduct alloc] initWithIdentifier:identifier_] autorelease];
}or
+(JGProduct *)productWithIdentifier:(NSString *)identifier_ {
return [[[self alloc] initWithIdentifier:identifier_] autorelease];
}Why would someone write either of these? The top one surely would not make the right kind of object if ran by a subclass. And what's the difference between
self and [self class] if you're in a class method?Thanks for any feedback!
Solution
Why
Imagine you have class A and its subclass B sharing the same designated initializer,
As you can see, the declarations have a conflicting return type, which unavoidably causes a compiler warning. You can trivially fix it by changing the methods to return
Why class initializers should use
As you correctly noticed, using
Why write
Most of the time, it's just a shortcut to
-init... should be declared to return idImagine you have class A and its subclass B sharing the same designated initializer,
initWithString:.@interface A : NSObject
-(A *) initWithString: (NSString *) string;
@end
@interface B : A
-(B *) initWithString: (NSString *) string;
@endAs you can see, the declarations have a conflicting return type, which unavoidably causes a compiler warning. You can trivially fix it by changing the methods to return
id, which, given Objective-C dynamic typing, doesn't change anything about how these methods work. So it has become a well-established, but not as well-understood, tradition.Why class initializers should use
self rather than the class nameAs you correctly noticed, using
JGProduct instead of self will allocate an instance of JGProduct for any subclass, which is not what you want in 99% cases.Why write
+[JGProduct productWithIdentifier:]?Most of the time, it's just a shortcut to
alloc, init and autorelease to make calling code more readable. However, these initializers may be much more complicated and more efficient when implemented in class clusters. When you write a class cluster, you have one public superclass and several private subclasses. In such cases the superclass's alloc has to return a placeholder object which will allocate and instantiate an object of the right subclass in its init... implementation. The class initializer, on the other hand, can immediately return an already inited object of the right subclass.Code Snippets
@interface A : NSObject
-(A *) initWithString: (NSString *) string;
@end
@interface B : A
-(B *) initWithString: (NSString *) string;
@endContext
StackExchange Code Review Q#9130, answer score: 4
Revisions (0)
No revisions yet.