2016-06-19 46 views
2

一個類有一些變量需要在init()中初始化,同時該類提供了一個函數來將這些變量恢復爲restoreInitValues()中的初始值。有沒有什麼辦法可以在init()restoreInitValues()的內部設置這些值兩次(重複代碼)?如何在初始化變量時防止重複代碼?

class Foo { 
    var varA: Int 
    var varB: Int 
    var varC: Int 

    init() { 
     //restoreInitValues() // error: call method before all stored proproties are initalized 

     //or I have to have duplicate code here as restoreInitValues below 
     varA = 10 
     varB = 20 
     varC = 30 
    } 

    func restoreInitValues() { 
     varA = 10 
     varB = 20 
     varC = 30 
    } 
} 
+0

你可以在報關行分配值,而忽略'init' – vadian

回答

1

就我個人而言,我會將3個默認值分配給3個類範圍常量,然後使用這些值來初始化和恢復。如果需要,還可以消除init中的賦值語句,並在聲明var時分配值。此外,如果您需要將其他任何功能添加到課程中,則可以使課程中定義的默認值保持不變,以供其使用。

class Foo { 
let defaultA = 10 
let defaultB = 20 
let defaultC = 20 
var varA: Int 
var varB: Int 
var varC: Int 

    init() { 
    varA = defaultA 
    varB = defaultB 
    varC = defaultC 
    } 

    func restoreInitValues() { 
    varA = defaultA 
    varB = defaultB 
    varC = defaultC 
    } 
} 

您還可以定義一個結構體,用它來分配您的值,然後使用您的重置函數來初始化。

struct values{ 

static let defaultA = 10 
static let defaultB = 20 
static let defaultC = 30 

} 


class test { 

var a: Int = 0 
var b: Int = 0 
var c: Int = 0 

    init(){ 
     resetValues() 
    } 

    func resetValues(){ 

     (a, b, c) = (values.defaultA, values.defaultB, values.defaultC) 

    } 

} 
1

更新:Code's answer belowImplicitly Unwrapped Optionals就是答案。我不知道爲什麼我以前在文檔中找不到它。我將離開我的後代的答案,但你應該接受Code's answer

是swift的新手,我試了一下,發現了這兩個解決方案,但我不確定它們是否是最好的解決方案。

問題似乎是,swift盡力確保在執行初始化後沒有任何類實例會有未初始化的屬性(除非它們被標記爲可選)。它不會讓你調用非靜態方法,因爲你可能在所有屬性設置之前使用該實例。另外,它不相信你會調用另一個方法來初始化所有的屬性,這可能是因爲這很難驗證。

對於類,使用私有靜態方法返回默認值:如果您不需要類

class Foo { 
    //... 
    init() { 
    (varA, varB, varC) = Foo.defaultValues() 
    } 

    func restoreInitValues() { 
    (varA, varB, varC) = Foo.defaultValues() 
    } 

    static private func defaultValues() -> (Int, Int, Int) { 
    return (10, 20, 30) 
    } 
} 

,結構是可複製的價值:

struct Foo { 
    //... 
    mutating func restoreInitValues() { 
    self = Foo() 
    } 
} 

,或者你可以給在restoreInitValues(),只是這樣做:

var f = Foo() 
f.varA = 10000 
// instead of resetting the internal state of `f`, just replace it with 
// a new `Foo` instance 
f = Foo() 

或者你可以使用靜態私人我以修改Foo實例,但要繞過編譯器,必須使您的屬性成爲可選項。該解決方案有一個明確的伊克因素:

class Foo { 
    var varA: Int? 
    var varB: Int? 
    var varC: Int? 

    init() { 
    Foo.resetValues(in: self) 
    } 

    func restoreInitValues() { 
    Foo.resetValues(in: self) 
    } 

    static private func resetValues(in foo: Foo) { 
    foo.varA = 10 
    foo.varB = 20 
    foo.varC = 30 
    } 
} 

這使我們回到問題的心臟:迅速要求所有屬性是可選的或初始化。另一種解決方案是簡單地給出所有的屬性值(無意義或無意義)。缺點是屬性定義可能會誤導有人第一次閱讀代碼。

class Foo { 
    var varA = -1 
    var varB = -1 
    var varC = -1 

    init() { 
    restoreInitValues() 
    } 

    func restoreInitValues() { 
    varA = 10 
    varB = 20 
    varC = 30 
    } 
} 

最後,檢查出的答案,這樣類似的問題:How to implement two inits with same content without code duplication

+1

我們必須已在同一時間編輯,偉大的人笑 – Haligen

1

使用隱式展開自選。

class Foo { 
    var varA: Int! 
    var varB: Int! 
    var varC: Int! 

    init() { 
     restoreInitValues() 
    } 

    func restoreInitValues() { 
     varA = 10 
     varB = 20 
     varC = 30 
    } 
}