2014-09-01 91 views
5

在Swift中,應該在當前類的所有屬性初始化後調用super的初始化程序。然而,Objective-C init並未完成此操作,其中在初始化當前類中的屬性之前先調用super init。Swift超級初始化程序

Swift試圖通過強制執行來防止什麼問題?爲什麼Objective-C能夠避免Swift試圖阻止的問題?

+0

我可能還會提到,爲什麼在Objective-C中,應該在調用超類初始化程序之後初始化狀態*,這是因爲超類初始化程序可能會返回其調用該對象的不同對象。因此,如果你在調用超類初始化之前設置了一些狀態,它將被設置在錯誤的對象上(原來的'self',而不是後面的'self')。Swift沒有這個問題,因爲Swift中的初始化器不能返回除被調用的對象之外的對象(除了從Objective-C導入的初始化器之外)。 – newacct 2014-09-01 05:41:45

回答

10

初始化所有成員的哪些問題是斯威夫特試圖阻止通過強制執行呢?

這是一個很好的問題,Objective-C並沒有避免它。

問題是,當你在一個初始化方法中時,該對象在技術上處於部分構造狀態。 Bryan's post是一個很好的(儘管人爲的)例子。一般的問題是,如果一個超類的初始化方法調用一個方法,那麼一個子類可能會覆蓋這個方法。這本身並不是一件壞事。如果重寫的方法假設對象是完全構建的,則會出現問題。

但是,由於該對象仍然在調用初始化程序的過程中,情況並非如此。在對[super init]的調用返回並且對象的類執行其任何初始化代碼之前,該對象不是全部構造的。

dealloc方法有一個相關的問題:如果您調用方法中的方法,那些方法可能會假定該對象是完全構建的,而實際上它可能會被部分解構。這不是ARC之下的一筆交易,但它仍然會導致一些非常微妙的錯誤。

與SWIFT,該決定是通過強制執行這個規則,以避免這些類型的問題:

由你決定打電話super的時候,調用的類必須完成任何特定類的初始化。

這個規則的一個變體是:

你可能不調用方法,直到您叫super的初始化之後。

有了這個規則,您將永遠不會遇到上述問題。

5

ObjC不會避免任何事情。

對於這個ObjC代碼,它崩潰了,因爲父類試圖從子類訪問伊娃。如果使用Swift規則,可以檢測/避免。即前[super init]

@interface Parent : NSObject 

@property (readonly) int value; 

@end 

@implementation Parent 

- (id)init { 
    self = [super init]; 
    if (self) { 
     NSLog(@"%d", self.value); // call a method, which can be overrided by child class 
    } 
    return self; 
} 

- (int)value { 
    return 42; 
} 

@end 

@interface Child : Parent 

@end 

@implementation Child { 
    int *_valuePtr; 
} 

- (id)init { 
    self = [super init]; // call self.value 
    if (self) { 
     // to avoid crash, move this line before [super init], but it may have other undesired effect. e.g. when [super init] return another instance 
     _valuePtr = calloc(sizeof(int), 1); 
    } 
    return self; 
} 

- (void)dealloc { 
    free(_valuePtr); 
} 

- (int)value { 
    return *_valuePtr; 
} 

- (void)setValue:(int)value { 
    *_valuePtr = value; 
} 

@end 
+0

謝謝布萊恩。爲什麼你決定在這個例子中使用int指針而不是int? – Boon 2014-09-01 13:02:18

+1

@Boon他使用了一個指針,因爲這是一個讓它崩潰的簡單方法。當'super'初始化器調用'-value'時,使用子類實現。但是,子類尚未完成初始化,因此'_valuePtr'爲'NULL',並且取消引用'NULL'指針會導致應用程序崩潰。換句話說,子類的'-value'的實現假定對象只有在對象完全初始化時纔會被調用。在Objective-C中這是一個有缺陷的假設,並且是問題所在。 – 2014-09-01 20:53:50