Swift 4.2-返回在函数内部创建的类

时间:2019-01-08 21:00:30

标签: swift

我想声明一个工厂来帮助我创建用于测试的单例类实例,而无需清除测试运行之间的类级别状态。我的想法是使用工厂返回在函数内部声明的类。

我的假设是,该类将在运行时创建,并且仅在保留返回的引用的情况下才保留。例如:

protocol TestClassFactory {
    static func make() -> TestClass.Type
}

protocol TestClass {
    static var testValue: String { get set }
}

class Factory: TestClassFactory {
    static func make() -> TestClass.Type {
        class Tester: TestClass {
            static var testValue = "Unmodified"
        }

        return Tester.self
    }
}

但是,实际上,这没有按预期进行。具体来说,在第一个make()返回值上设置的静态值会一直保留到第二个返回值。

var testClass1 = Factory.make()
print(testClass1.testValue)        // "Unmodified"
testClass1.testValue = "Modified"
print(testClass1.testValue)        // "Modified"

var testClass2 = Factory.make()
print(testClass2.testValue)        // "Modified" 

Swift运行时似乎将类保留在其内部,就像在编译时声明和引用的类一样。

我的问题:

  1. 有人参考描述这种行为是否有意吗?我以为是,但是想确定。
  2. 对于我的特定用例,除了使用某种反射/镜像来动态生成类型外,我是否还有其他选择?

1 个答案:

答案 0 :(得分:2)

Swift能够在运行时创建新类型,但是我认为当前无法以语言用户的身份使用该功能。

在Swift中,并非所有语句都是可执行的:有些代码仅在编译时进行评估,因此不会产生任何可执行代码。类语句就是其中之一。在运行时不会评估类范围以创建新类:编译器会看到一个类语句,构建该类,并为您提供对该类的静态引用。这样,当您创建类时,不会在程序启动时(或在任何其他时间)执行任何代码。这与其他语言(例如Python)形成对比,在Python中,每个语句都固有地可执行,而执行class语句实际上会创建一个类。

当您尝试在函数局部类内部使用局部变量时,错误会突出此行为:

func foo(int: Int) {
    class Bar {
        let f = int
        // error: class declaration cannot close over value 'int' defined in outer
        // scope
    }
}