使用 "id" 作为自定义 "init" 方法的 return 类型而不是指向 class 的指针的优缺点?
Pros and cons of using "id" as the return type of a custom "init" method, instead of a pointer to that class?
假设以下 Objective-C class:
@interface Appliance : NSObject
{
NSString *productName;
int voltage;
}
@end
实施 init 方法 A 而不是 B 的优缺点是什么?
A) -(id)initWithName:(NSString *)name;
B) -(Appliance *)initWithName:(NSString *)name;
我看到它们都在 XCode 中工作,即它们都会产生一个有效的 Appliance 实例。 "A" 似乎是我读过的书和看过的代码库中的标准,我想知道为什么会这样。
事实上,在相当长一段时间内,来自 class 初始值设定项(在 Objective-C 中)的最佳实践 return 类型是 instancetype
而不是 id
.
哦,重新打开。 :-)
确实,您没有问 id
与 instancetype
的区别。对于 -init…
这个非问题的答案很简单:没有区别,因为编译器会默默地将 id
转换为 instancetype
。
您要求 id
与 CustomClass*
。你从我那里得到一个完全不同的答案:对于 CustomClass*
,subclass 必须转换 superclass' 指定初始化程序的结果。让我们举个例子:
@interface BaseClass : NSObject
- (BaseClass*)initWithWhatever; // Typed to class, designated initializer
@end
@implementation BaseClass
- (BaseClass*)initWithWhatever // Typed to class
{
self = [super init]; // What's the return type of -init (NSObject)?
…
}
@end
@interface Subclass : BaseClass
// First problem: I like it to announce in the interface, that a class overwrites
// a method of the base class. Doing so I would have to change the return type. Ugly.
// If I do not redeclare -initWithWhatever it is inherited from BaseClass, still
// having BaseClass* as the return type. Is that the truth? Really?
// However, I do not overwrite it here, but have a new initializer.
- (Subclass*)initWithSomethingElse;
@end
@implementation Subclass
- (Subclass*)initWithSomethingElse
{
// Second Problem:
// First, I have to execute the superclass' designated initializer
self = [super initWithWhatever];
// Wait a minute!
// self is a reference to Subclass. The return value of -initWithWhatever has the type
// BaseClass*. So I assign a reference of the base class to a reference of the subclass:
// Compiler error, false positive. The code is correct.
// So I would have to cast. Ugly, ugly, ugly.
@end
…
// Third problem:
Subclass *object = [[Subclass alloc] initWithWhatever];
// Typing -initWithWhatever to BaseClass* would lead to a compiler error here again.
// Compiler error, false positive. The code is correct.
长话短说:如果没有大量的铸件,就不可能将初始值设定项键入具体的 class。
假设以下 Objective-C class:
@interface Appliance : NSObject
{
NSString *productName;
int voltage;
}
@end
实施 init 方法 A 而不是 B 的优缺点是什么?
A) -(id)initWithName:(NSString *)name;
B) -(Appliance *)initWithName:(NSString *)name;
我看到它们都在 XCode 中工作,即它们都会产生一个有效的 Appliance 实例。 "A" 似乎是我读过的书和看过的代码库中的标准,我想知道为什么会这样。
事实上,在相当长一段时间内,来自 class 初始值设定项(在 Objective-C 中)的最佳实践 return 类型是 instancetype
而不是 id
.
哦,重新打开。 :-)
确实,您没有问 id
与 instancetype
的区别。对于 -init…
这个非问题的答案很简单:没有区别,因为编译器会默默地将 id
转换为 instancetype
。
您要求 id
与 CustomClass*
。你从我那里得到一个完全不同的答案:对于 CustomClass*
,subclass 必须转换 superclass' 指定初始化程序的结果。让我们举个例子:
@interface BaseClass : NSObject
- (BaseClass*)initWithWhatever; // Typed to class, designated initializer
@end
@implementation BaseClass
- (BaseClass*)initWithWhatever // Typed to class
{
self = [super init]; // What's the return type of -init (NSObject)?
…
}
@end
@interface Subclass : BaseClass
// First problem: I like it to announce in the interface, that a class overwrites
// a method of the base class. Doing so I would have to change the return type. Ugly.
// If I do not redeclare -initWithWhatever it is inherited from BaseClass, still
// having BaseClass* as the return type. Is that the truth? Really?
// However, I do not overwrite it here, but have a new initializer.
- (Subclass*)initWithSomethingElse;
@end
@implementation Subclass
- (Subclass*)initWithSomethingElse
{
// Second Problem:
// First, I have to execute the superclass' designated initializer
self = [super initWithWhatever];
// Wait a minute!
// self is a reference to Subclass. The return value of -initWithWhatever has the type
// BaseClass*. So I assign a reference of the base class to a reference of the subclass:
// Compiler error, false positive. The code is correct.
// So I would have to cast. Ugly, ugly, ugly.
@end
…
// Third problem:
Subclass *object = [[Subclass alloc] initWithWhatever];
// Typing -initWithWhatever to BaseClass* would lead to a compiler error here again.
// Compiler error, false positive. The code is correct.
长话短说:如果没有大量的铸件,就不可能将初始值设定项键入具体的 class。