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

Pal*_*tim 5 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
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,在实践中,这并没有按预期工作。具体来说,在第一个make()返回值上设置的静态值会保留到第二个返回值中。

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

var testClass2 = Factory.make()
print(testClass2.testValue)        // "Modified" 
Run Code Online (Sandbox Code Playgroud)

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

我的问题:

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

zne*_*eak 2

Swift 能够在运行时创建新类型,但我认为当前不可能作为语言用户使用该功能。

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

当您尝试在函数局部类中使用局部变量时,错误会强调此行为:

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