Arrays 单个数组元素的惰性初始化

Arrays 单个数组元素的惰性初始化,arrays,swift,lazy-initialization,Arrays,Swift,Lazy Initialization,在Swift中,允许我们仅在请求时初始化类成员,而不是在运行时直接初始化,这对于计算代价高昂的操作非常有用 我在Swift 4中有一个类,负责从StrategyProtocol对象提供的编译时数组(开发人员硬编码)初始化一个。它看起来像这样: class StrategyFactory { private var availableStrategies: [StrategyProtocol] = [ OneClassThatImplementsStrategyProtoc

在Swift中,允许我们仅在请求时初始化类成员,而不是在运行时直接初始化,这对于计算代价高昂的操作非常有用

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

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
放在
数组
类成员中的某个值周围,以便在请求时仅实例化所需的值?或者我必须用闭包或其他方法来解决这个问题


当前尝试 这就是我想的吗?在我得到数组的第一个元素并执行它之前,它实际上不会实例化策略

private var availableStrategies: [() -> (StrategyProtocol)] = [
    { OneClassThatImplementsStrategyProtocol() }
]
我可以回答你的问题。(我不是Swift专家,但元类的使用可能是您想要的,正如我所料,Swift似乎支持它们。)您可以查看这个堆栈溢出

编辑:如果不清楚,我们的想法是让策略数组包含协议的元类,而不是实例化。尽管这取决于您是否希望为具有lazy属性的类的每个实例化都使用一个新的策略对象,或者策略是否是有效的全局策略和创建的缓存策略。如果是后者,那么用于保存它们的惰性数组方法可能会更好。

您的“当前尝试”会做您认为它会做的事情。你有一个数组 并且只有在关闭时才初始化策略 执行

一种可能的替代方法是:存储类型数组,而不是 实例或闭包(as)

为了按需创建实例,需要
init()
满足
要求的init()
,除非该类是
最终的
, 比较)

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

下面是一个自包含的小示例,其中
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
    }
}

比较“你认为它做什么”OP可能不清楚数组元素没有被闭包的结果替换,这在我听来就像他在谈论惰性属性时所期待的一样。@Josh Caswell:这不是我的印象(来自“在我获得数组的第一个元素并执行它之前,它实际上不会实例化策略?”)–也许OP可以对此发表评论,如果有必要,我会澄清。我不希望闭包的结果会取代闭包。谢谢你的回答!我最终选择了闭包路线,因为我不喜欢添加
inits
,这不是我选择API的直接要求。但是我使用了
类型
s这似乎是一个很好的方法,所以我会把它标记为正确的。