使用“id”作为自定义“init”方法的返回类型的优缺点,而不是指向该类的指针?

时间:2015-07-21 03:40:59

标签: objective-c initialization

假设以下Objective-C类:

@interface Appliance : NSObject
{
    NSString *productName;
    int voltage;
}
@end

实现init方法A而不是B的优缺点是什么?

A) -(id)initWithName:(NSString *)name;
B) -(Appliance *)initWithName:(NSString *)name;

我发现它们都在XCode中工作,即它们都会产生有效的Appliance实例。 “A”似乎是我读过的书和我看过的代码库中的标准,我想知道为什么会这样。

2 个答案:

答案 0 :(得分:3)

事实上,很长一段时间,类初始值设定项(在Objective-C中)的最佳实践返回类型是instancetype而不是id

答案 1 :(得分:1)

哦,重新打开。 : - )

实际上,您没有要求区分idinstancetype。而对于-init…,这个非问Q的答案很简单:没有区别,因为编译器会默默地将id转换为instancetype

您要求idCustomClass*。而且你得到了一个完全不同的答案:使用CustomClass*子类必须转换超类的结果'指定初始化程序。让我们举个例子:

@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.

总而言之:没有大量的铸件,就不可能在具体的类中输入初始化器。