Quería declarar una fábrica para ayudarme a crear instancias de clases singleton para la prueba, sin la sobrecarga de borrar el estado de nivel de clase entre ejecuciones de prueba. Pensé en usar una fábrica para devolver una clase declarada dentro de una función.
Mi suposición era que la clase se crearía sobre la marcha y se conservaría solo mientras se mantuviera la referencia devuelta. Por ejemplo:
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 } } Sin embargo, en la práctica, esto no funcionó como se esperaba. Específicamente, un valor estático establecido en el primer valor de retorno de make() persistió en el segundo.
var testClass1 = Factory.make() print(testClass1.testValue) // "Unmodified" testClass1.testValue = "Modified" print(testClass1.testValue) // "Modified" var testClass2 = Factory.make() print(testClass2.testValue) // "Modified" 🤨El tiempo de ejecución de Swift parecía retener la clase en su forma como una clase declarada y referenciada en tiempo de compilación.
Mis preguntas:
Swift es capaz de crear nuevos tipos en tiempo de ejecución, pero no creo que actualmente sea posible usar esa capacidad como usuario de lenguaje.
En Swift, no todas las declaraciones son ejecutables: hay código que se evalúa solo en tiempo de compilación y no da como resultado un código ejecutable. Las declaraciones de clase son una de ellas. El alcance de la clase no se evalúa en tiempo de ejecución para crear una nueva clase: el compilador ve una declaración de clase, crea esa clase y le brinda una referencia estática a esa clase en el futuro. De esa manera, no se ejecuta ningún código al inicio de su programa (o en cualquier otro momento) cuando crea una clase. Esto contrasta con otros lenguajes, como Python, donde cada declaración es inherentemente ejecutable y ejecutar una declaración de clase en realidad crea una clase.
Este comportamiento es enfatizado por errores cuando intenta usar variables locales dentro de clases locales de funciones:
func foo(int: Int) { class Bar { let f = int // error: class declaration cannot close over value 'int' defined in outer // scope } }