2017-04-12 67 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