各个数组元素的延迟初始化

时间:2017-12-09 18:59:05

标签: arrays swift lazy-initialization

在Swift中,lazy properties允许我们只在我们请求它时而不是直接在运行时初始化一个类成员 - 对计算成本高昂的操作很有用。

我在Swift 4中有一个类,负责从编译时(开发人员硬编码)提供的StrategyProtocol对象数组中初始化strategy。它看起来像这样:

class StrategyFactory {
    private var availableStrategies: [StrategyProtocol] = [
        OneClassThatImplementsStrategyProtocol(),
        AnotherThatImplementsStrategyProtocol() // etc
    ]

    public func createStrategy(): StrategyProtocol {
        // Depending on some runtime-calculated operation
        // How do I do this nicely here?
    }
}

但是,根据我的理解,在每个策略结束时放置()会初始化对象(?),而我可能只想根据某些运行时条件创建一个。

无论哪种方式,是否可以在lazy类成员中的值周围放置Array以仅在我要求时实例化我想要的那个?或者我是否必须通过封闭或其他替代方案来解决这个问题?

当前尝试

这是我认为的吗?在我获得数组的第一个元素并执行它之前,它实际上不会实例化策略吗?

private var availableStrategies: [() -> (StrategyProtocol)] = [
    { OneClassThatImplementsStrategyProtocol() }
]

2 个答案:

答案 0 :(得分:2)

您当前的尝试"做你认为它做的。你有一个阵列 闭包,只有在闭包时才会初始化策略 执行。

一种可能的替代方法:存储一组类型而不是 实例或闭包(如Zalman Stern also suggested)。

为了按需创建实例,a 必须将init()要求添加到协议中(必须这样做 除非班级为required init(),否则请final满意, 比较Why use required Initializers in Swift classes?)。

一个可能的优点是您可以查询静态属性 为了找到合适的策略。

这是一个小型的自包含示例,其中createStrategy() 创造并返回第一个"梦幻般的"策略:

protocol StrategyProtocol {
    init()
    static var isFantastic: Bool { get }
}

class OneClassThatImplementsStrategyProtocol : StrategyProtocol {
    required init() { }
    static var isFantastic: Bool { return false }
}

final class AnotherThatImplementsStrategyProtocol : StrategyProtocol {
    init() { }
    static var isFantastic: Bool { return true }
}

class StrategyFactory {
    private var availableStrategies: [StrategyProtocol.Type] = [
        OneClassThatImplementsStrategyProtocol.self,
        AnotherThatImplementsStrategyProtocol.self // etc
    ]

    public func createStrategy() -> StrategyProtocol? {
        for strategy in availableStrategies {
            if strategy.isFantastic {
                return strategy.init()
            }
        }
        return nil
    }
}

答案 1 :(得分:0)

ANYCLASS, META TYPE AND .SELF可能会回答您的问题。 (我不是Swift的专家,但是使用元类很可能是你想要的,而Swift,正如我所料,似乎支持它们。)你可以看看这个Stack Overflow search

编辑:如果它不清楚,那么想法是让策略数组包含协议的元类而不是实例化。虽然这取决于您是否希望为具有惰性属性的类的每个实例化创建一个新策略对象,或者策略是否实际上是全局的,并且创建了缓存的策略。如果是后者,那么保持它们的懒惰数组方法可能会更好。