单个数组元素的延迟初始化
Lazy initialisation of individual array elements
在 Swift 中,lazy properties 允许我们仅在请求时初始化 class 成员,而不是直接在运行时初始化 - 对于计算量大的操作很有用。
我在 Swift 4 中有一个 class 负责从一组编译时(开发人员硬编码)提供的 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
class 成员值周围的某处,以便仅在我请求时实例化我想要的值?还是我必须通过闭包或其他替代方案来解决这个问题?
当前尝试
这是在按照我的想法行事吗?直到我得到数组的第一个元素并执行它,它才会真正实例化策略?
private var availableStrategies: [() -> (StrategyProtocol)] = [
{ OneClassThatImplementsStrategyProtocol() }
]
ANYCLASS, META TYPE AND .SELF may answer your question. (I am not expert on Swift, but use of metaclasses is likely what you want and Swift, as I expected, appears to support them.) You can look through this Stack Overflow search.
编辑:如果不清楚,我们的想法是让策略数组包含协议的元classes 而不是实例化。虽然这取决于您是否需要为 class 和惰性 属性 的每个实例化一个新的策略对象,或者策略是否是有效的全局策略和创建的缓存策略。如果是后者,那么保存它们的惰性数组方法可能会更好。
你的 "Current attempt" 做你想做的事。你有一个数组
闭包,并且策略仅在闭包被初始化时被初始化
已执行。
一个可能的替代方案:存储一个 types 的数组而不是
实例或闭包(如 )。
为了按需创建实例,一个
init()
要求必须添加到协议中(然后必须
被 required init()
满足,除非 class 是 final
,
比较 ).
一个可能的优势是您可以查询静态属性
以便找到合适的策略。
这是一个独立的小例子,其中 createStrategy()
创建并 returns 第一个 "fantastic" 策略:
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
}
}
在 Swift 中,lazy properties 允许我们仅在请求时初始化 class 成员,而不是直接在运行时初始化 - 对于计算量大的操作很有用。
我在 Swift 4 中有一个 class 负责从一组编译时(开发人员硬编码)提供的 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
class 成员值周围的某处,以便仅在我请求时实例化我想要的值?还是我必须通过闭包或其他替代方案来解决这个问题?
当前尝试
这是在按照我的想法行事吗?直到我得到数组的第一个元素并执行它,它才会真正实例化策略?
private var availableStrategies: [() -> (StrategyProtocol)] = [
{ OneClassThatImplementsStrategyProtocol() }
]
ANYCLASS, META TYPE AND .SELF may answer your question. (I am not expert on Swift, but use of metaclasses is likely what you want and Swift, as I expected, appears to support them.) You can look through this Stack Overflow search.
编辑:如果不清楚,我们的想法是让策略数组包含协议的元classes 而不是实例化。虽然这取决于您是否需要为 class 和惰性 属性 的每个实例化一个新的策略对象,或者策略是否是有效的全局策略和创建的缓存策略。如果是后者,那么保存它们的惰性数组方法可能会更好。
你的 "Current attempt" 做你想做的事。你有一个数组 闭包,并且策略仅在闭包被初始化时被初始化 已执行。
一个可能的替代方案:存储一个 types 的数组而不是
实例或闭包(如
为了按需创建实例,一个
init()
要求必须添加到协议中(然后必须
被 required init()
满足,除非 class 是 final
,
比较
一个可能的优势是您可以查询静态属性 以便找到合适的策略。
这是一个独立的小例子,其中 createStrategy()
创建并 returns 第一个 "fantastic" 策略:
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
}
}