Плюсы и минусы использования "id" в качестве возвращаемого типа пользовательского метода "init" вместо указателя на этот класс?

Предположим, что следующий класс Objective C:

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

Каковы плюсы и минусы реализации метода инициализации A вместо B?

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

Я вижу, что они оба работают в XCode, т.е. они оба приведут к действительному экземпляру Appliance. Кажется, буква "А" является стандартом среди книг, которые я прочитал, и баз кодов, на которые я смотрел, и мне интересно, почему это так.

2 ответа

Решение

О, открой заново.:-)

Действительно, вы не просили разницы id против instancetype, И для -init… Ответ на этот незапрошенный Q будет легким: нет никакой разницы, потому что компилятор преобразует id в instancetype молча.

Вы просили id против CustomClass*, И вы получите от меня совершенно другой ответ: 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.

Короче говоря, без массы отливок было бы невозможно набрать инициализаторы для конкретного класса.

Дело в том, что в течение достаточно долгого времени наилучший тип возвращаемого значения из инициализатора класса (в Objective-C) instancetype вместо id,

Другие вопросы по тегам