2014-01-12 52 views
2

我有一個簡單的類層次結構,其構造函數使用instancetype而不是id作爲返回類型。如果我想轉發給超類的構造函數,我得到這樣的警告:使用實例類型與ID的類層次結構

返回車輛*從方法*返回車:接口車輛沒有車

如果我切換的繼任者從instancetypeid,當然,由於類型嚴格性較低,錯誤消失。推薦的方法是什麼?

Vehicle.h

@interface Vehicle 

- (instancetype)initWithIdentifier:(NSString *)anIdentifier 

@end 

Vehicle.m

@implementation Vehicle 

- (instancetype)initWithIdentifier:(NSString *)anIdentifier { 
    self = [super init]; 

    if (self) { 
     // do a bunch of stuff to construct the object 
    } 

    return self;  
} 

@end 

Car.h

@interface Car : Vehicle 

- (instancetype)initWithCarID:(NSString *)aCarId 

@end 

Car.m

@implementation Car 

- (instancetype)initWithCarID:(NSString *)aCarId { 
    // I want to forward the call to the parent and preserve the 
    // two different constructor signatures 

    // The following line produces this warning: 
    // Returning Vehicle * from a method returning Car *: interface Vehicle is not a successor of Car 
    return [super initWithVehicleIdentifier:aCarId]; 
} 

@end 

回答

1

對於-init*方法,這是instancetype是不必要的。編譯器會自動將id視爲instancetype

自己嘗試一下,看看有什麼警告,從下面的代碼生成:

[[[NSArray alloc] init] length]; 
[[[NSArray alloc] initWithContentsOfURL:nil] length]; 

見NSHipster年代instancetype書面記錄更多的細節。


更新

作爲一項規則,instancetype爲返回自己的一個實例的任何方法是有用的。由於命名約定規則,-init*只是此規則的一個例外。

Objective-C就像英文語法:每條規則都有例外。

+0

因此instancetype只對類構造函數是必需的嗎? –

+0

隱含相關結果類型的方法是'alloc','+ new','-init','-retain','-autorelease'和'-self',@Will。更多細節[在Clang文檔中](http://clang.llvm.org/docs/LanguageExtensions.html#related-result-types)。 –

+0

@我會更新我的答案。 –

1

我會用「ID」,因爲其通常的方式來實現這樣的事情 - 看到蘋果的示例代碼等,如果你真的想用instancetype然後與獅子座的答案去。

你得到警告的原因是因爲「Vehicle」(你正在返回的)的一個實例並不完全是「Car」的一個實例。它會工作,但你已經告訴編譯器該方法將返回一個「Car」的實例。 有關更多信息,請參閱此question

1

嘗試以下操作:

@implementation Car 
- (instancetype)initWithCarID:(NSString *)aCarId { 

    self = [super initWithVehicleIdentifier:aCarId]; 
    return self; 
} 

或者,乾脆將返回的對象:

- (instancetype)initWithCarID:(NSString *)aCarId { 
    return (Car*)[super initWithVehicleIdentifier:aCarId]; 
}