2016-06-30 31 views
2

我對swift很陌生,並且正在初始化一些問題。我已經創建了下面的代碼迅速文件:爲什麼超類指定的初始化程序默認被調用?

import Foundation 

class SuperClass 
{ 
    var a : Int 
    init() 
    { 
     a = 10 
     print("In Superclass") 
    } 
} 

class SubClass : SuperClass 
{ 
    override init() 
    { 
     print("In Subclass") 
    } 
} 

在上面的代碼中,​​init()不包含調用的SuperClassinit()即存在SubClass init()沒有super.init()

所以我的問題是:

  1. 爲什麼不給任何錯誤,如果我不叫指定的SuperClass

  2. init()如果我創造的​​即let s = SubClass()的對象時,輸出爲:

    In子類

    在Superclass

爲什麼的init()被調用?一個子類init()默認調用超類init()嗎?

請幫忙.. !!!

回答

0

您沒有訪問子類中的超類變量,因此會調用super.init(),然後調用子類的init。但是,如果您嘗試在不調用其初始化函數的情況下在子類中使用超類變量,則會導致編譯時錯誤。

+0

[蘋果文檔] [https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID203] ]表示該子類必須調用超類指定的初始化程序。你能用任何證據支持你的陳述嗎? – PGDev

0

我沒有這個嘗試我自己,但Swift Language Guide說:

初始值設定代表團類的類型

爲了簡化指定和便利的初始化之間的關係,斯威夫特應用以下三個規則用於初始化程序之間的委託調用:

規則1

指定的初始值設定項必須從它的直接超類中調用指定的初始值設定項。

規則2

的簡便初始化必須調用從相同類的另一個初始化。

規則3

的簡便初始化必須最終調用指定初始化。

一個簡單的方法來記住這個:

指定的初始值必須始終委派了。

便捷初始值設定項必須始終進行委派。

所以,它是一個「規則」來調用super.init(),它可能只是內部完成,如果沒有明確落實。

+2

但它無處寫道,它被稱爲內部。 – PGDev

+0

你也可以看看下面的問題:https://stackoverflow.com/questions/25257224/does-a-swift-subclass-always-have-to-call-super-init – Flo

+0

我看了帖子..但仍然沒有給出super.init()被內部調用的任何證明。 – PGDev

0

每個班級至少有一個指定的初始化程序它負責初始化實例變量。

下面是從文檔的摘錄:

類往往有極少數指定的初始化程序,這是很常見的一個類只有一個。指定的初始化器是通過初始化發生的「漏斗」點,並且初始化過程通過它繼續超類鏈。

每個班級必須至少有一個指定的初始值設定項。在某些情況下,通過從超類繼承一個或多個指定的初始值設定項來滿足此要求,如下面的Automatic Initializer Inheritance中所述。

您可以參閱完整的文檔,瞭解更多詳情:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html

拇指

  1. 的規則創建類一個指定的初始化。
  2. 調用超類的指定初始值設定項,或讓系統爲您弄清楚。
  3. 創建零個或多個便利初始值設定項,它將調用您指定的初始值設定項。
+0

但是,如果我們在子類中給出自己指定的初始值設定項,則超類初始值設定項不會被繼承。爲什麼它會被默認調用? – PGDev

+1

如果你給自己指定的初始值設定項,你必須調用超類的指定初始值設定項。如果你不這樣做,編譯器會爲你選擇一個,因爲超類實例變量必須被初始化! – nverinaud

1

據我瞭解您的問題,您不僅想知道爲什麼,何時以及如何自動調用初始化程序,還抱怨此行爲缺少文檔。

首先我同意你缺乏文檔 - 就像你我無法找到任何關於此行爲的內容,因此它應該被添加到Apple的文檔中。

爲什麼super.init()被稱爲:

按照文檔的超類的指定初始化必須由它的子類的指定初始化才能完全初始化所有屬性被調用。

規則1

一個指定初始化必須從它的 直接超類調用指定的初始化。上述

你的代碼示例證明了這一點顯然隱式進行:print("In Superclass")打印到控制檯上,所以當創建一個實例super.init()以某種方式調用。

何時以及如何super.init()被稱爲:

有一些條件,以便讓編譯器調用隱含超類的指定初始化得到滿足:

  1. 的超類必須只有一個指定的初始化程序,然後調用 。否則,編譯器必須選擇一個委託 。這個單指定的初始化器也可以是默認的初始值設定項或一個繼承的初始值設定項。

    class SuperClass { 
        var a: Int 
        init() { 
         a = 10 
        } 
        // introduction of a second designated initializer in superclass: 
        init(withValue value: Int) { 
         a = value 
        } 
    } 
    
    class SubClass: SuperClass { 
        // won't compile: 
        // "error: super.init isn't called on all paths before returning from initializer"    
        override init() {} 
    } 
    
  2. 超類的單一指定初始化不得有任何 參數。畢竟編譯器不知道任何合適的 參數傳遞。

  3. 子類的指定初始化不能進一步讀取或修改 (繼承)的超類的實例的屬性或調用超的 實例方法。這是因爲Swift的 兩階段初始化過程及其相應的安全性 檢查以及超類別的指定 初始化程序的隱式委派發生在子類的陳述結束處。

    安全檢查2

    甲指定初始化必須以一種遺傳 屬性分配值之前委派到一個超類 初始化。如果沒有,新值指定初始化 受讓人將由超作爲自己 初始化的一部分覆蓋。「

    安全檢查4

    一個初始化不能調用任何實例方法,閱讀 任何實例屬性的值,或者直到第一階段的初始化完成後,將自身指定爲值 。

    class SuperClass { 
        var a: Int 
        init() { 
         a = 10 
        } 
    } 
    
    class SubClass: SuperClass { 
        // won't compile: 
        // "error: use of 'self' in property access 'a' before super.init initializes self"    
        override init() { 
         a = 10 // modifying inherited self.a before phase 1 of initialization completes isn't valid! 
         // implicit delegation to super.init() 
        } 
    } 
    

    安全檢查1

    一個指定初始化必須確保所有通過它的類推出 屬性都纔到一個超類的初始化初始化 代表。

    class SuperClass { 
        var a: Int 
        init() { 
         a = 10 
        } 
    } 
    
    class SubClass: SuperClass { 
        // introduction of instance property "b" 
        var b: Int 
        // compiles finely: 
        override init() { 
         b = 10 // initializing self.b is required before delegation! 
         // implicit delegation to super.init() 
        } 
    } 
    

我希望幫助。

1

爲什麼SuperClass的init()被調用?子類init()默認調用超類init()

基本上,是的。

如果所有的規則都說你應該說super.init()而你沒有說出來,那麼它就是你要求的。

我不喜歡這種行爲;它記錄不完善,此外,偷偷爲你做東西似乎違背了斯威夫特的精神。但是我很久以前就提出了一個錯誤,並被告知它是有意的行爲。

相關問題