2017-04-12 106 views
3

我意識到static變量隱含爲lazy,這真的很棒。做下面不會創建實例,直到它的第一個叫:設置lazy靜態變量先初始化然後賦值?

static var test = Test() 

然而,到了static變量分配一個新的實例初始化原,然後分配這是困擾我的新實例:

SomeType.test = AnotherTest() //Initializes Test then AnotherTest type 

爲了給我更多的背景,我正在嘗試使用this article設置一個純Swift依賴注入。在我的單元測試中交換類型時效果不佳,因爲原始類型在分配模擬類型時總是被初始化。

這裏有一個更全面的多,操場樣本:

protocol MyProtocol { } 

class MyClass: MyProtocol { 
    init() { print("MyClass.init") } 
} 

//// 

struct MyMap { 
    static var prop1: MyProtocol = MyClass() 
} 

protocol MyInject { 

} 

extension MyInject { 
    var prop1: MyProtocol { return MyMap.prop1 } 
} 

//// 

class MyMock: MyProtocol { 
    init() { print("MyMock.init") } 
} 

// Swapping types underneath first initializes 
// original type, then mock type :(
MyMap.prop1 = MyMock() 

prints: MyClass.init 
prints: MyMock.init 

我怎樣才能讓MyMap.prop1 = MyMock()不首先初始化原MyClass第一?

回答

2

您需要延遲加載。試試這個:

struct MyMap { 
    private static var _prop1: MyProtocol? 
    static var prop1: MyProtocol { 
     get { return _prop1 ?? MyClass() } 
     set(value) { _prop1 = value } 
    } 
} 

或者這樣:

struct MyMap { 
    private static var _prop1: MyProtocol? 
    static var prop1: MyProtocol { 
     get { 
      if _prop1 == nil { 
       _prop1 = MyClass() 
      } 
      return _prop1! 
     } 
     set(value) { _prop1 = value } 
    } 
} 
+0

哇,爲什麼這項工作?..這是斯威夫特的錯誤或者是故意這樣!? – TruMan1

+1

它的意圖是迅速。一個var只要存在就需要一個值。該值可能爲零或具體。您的var不能由您的定義爲零,因此您必須指定一個值(或者編譯出錯)。如果您調用get或set,則無關緊要。在使用Swift之前,Swift必須確保你的var有一個值。那就是蘋果所謂的「快速救人」。 – ObjectAlchemist

+0

@codealchimist但是'static'存儲的屬性被延遲加載 - 如果它在加載之前首先被分配給它,它不應該*調用屬性初始值。但這只是目前Swift的行爲。 – Hamish