我正在开发一个具有很多功能的课程。有些函数需要很多时间,因此我会将结果存储在创建中以供以后访问。但如果永远不需要这个值,那么计算就是浪费时间。
在这种情况下,如果已经计算了值,我将使用标记。如果是,请使用存储的值。如果没有,它将计算该值并将其存储在其静态变量中。
所以我需要函数本身,一个标记和一个保存结果的变量。每个功能有三个项目! 在Swift中是否存在类似于"可选的静态函数" ??
我更愿意使用
a = function()
每次通话都。第一个调用将计算并保存结果,所有其他调用只会采用预先计算的结果(如缓存)。
答案 0 :(得分:1)
在下面的评论中,您描述了
但我并不是指全局静态值,而是针对每个实例。所以 如果您使用
foo1
和foo2
,则foo2
需要计算自己的foo2
它本身的功能,因为它只取决于foo1
的值。它 不能依赖之前完成的全球计算版本 按Foo
。所以它就像一个“局部静态变量”
因此,似乎您可能对Foo
的每个实例进行大量计算,并且您希望确保此计算最多执行一次,对于每个给定的{ {1}}。这个需求非常接近Swift中懒惰(存储)属性的定义:如果第一次调用以获取给定的lazy属性的值,则该属性将被实例化(例如,通过调用某个方法,执行一次只执行的闭包,或者只是通过给定的值/ literal),以及存储在属性中的值。对lazy属性的所有后续调用将仅使用存储的值(假设您不选择改变属性:lazy instance properties可能不是不可变的。)
例如,在实践中:
class Foo {
lazy var bar: Int = self.reallyHeavyCalculation()
lazy var baz: Int = {
print("... heavy stuff")
return 2 * self.baq
}()
private func reallyHeavyCalculation() -> Int {
// ...
print("... other heavy stuff")
return 42
}
var bax: Int?
var baq: Int // instance value used in once-only computation
// of (lazy) property baz: at baz instantiation
init(baq: Int) { self.baq = baq }
}
let foo1 = Foo(baq: 50)
print("My first foo has never accessed his bar or baz")
foo1.bax = foo1.bar // at first call: compute 'bar' for this Foo instance
var baxBaz = foo1.bar // 'foo1.bar' already computed
print(foo1.baz) // at first call: compute 'baz' for this Foo instance
baxBaz = foo1.baz // 'foo1.baz' already computed
/* Prints:
My first foo has never accessed his bar or baz
... other heavy stuff
... heavy stuff
100 */
(当我最初阅读你的问题时,我认为你的用例是类/静态属性,只计算一次。我将留下这部分答案,因为它仍然与这个主题,可能对未来的读者有所帮助)
静态属性总是懒惰地计算,这意味着它们只会使用给定至少一次调用的值进行实例化。在该实例化之后,例如,在静态不可变属性的情况下,只有一次计算的值很容易获得并存储在静态属性中。
我们可以阅读the Language Guide - Properties:
输入属性
...
存储类型属性在首次访问时会被懒惰地初始化。 它们只保证初始化一次,即使访问时也是如此 多个线程同时进行,不需要标记 使用
lazy
修饰符。...
全局和局部变量
...
全局常量和变量总是在a中懒惰地计算 与Lazy Stored Properties类似的方式。与懒惰存储不同 不需要标记属性,全局常量和变量 使用
lazy
修饰符。
我们可以通过简单的示例验证此行为:
class Foo {
static let foo: Int = reallyHeavyCalculation() // lazy
static let bar: Int = {
print("... heavy stuff")
return 99
}() // lazy
private static func reallyHeavyCalculation() -> Int {
// ...
print("... other heavy stuff")
return 42
}
var bax: Int? = nil
var baz = Foo.bar
}
print("I've never had a foo")
let foo1 = Foo()
// first initializion of instance member 'baz' by
// type member 'bar': compute bar
print("I have a foo")
foo1.bax = Foo.foo // at first call: compute 'Foo.foo'
let foo2 = Foo() // 'Foo.bar' already computed
print("I have another foo")
foo2.bax = Foo.foo // 'Foo'foo' already computed
/* Prints:
I've never had a foo
... heavy stuff
I have a foo
... other heavy stuff
I have another foo */
在上面的示例中,如果您要求(至少一次)静态不可变属性{reallyHeavyComputation()
,则Foo.bar
(与Foo.foo
)关联的闭包方法将被调用一次。 1}}(/ Foo.bar
)。即使您反复要求reallyHeavyComputation()
(/ Foo.foo
)值,也不会对Foo.bar
(/ closure)进行其他调用。