懒让?结构中的快速解决方法
Lazy let? Unswifty workaround in structs
我有一个正在使用的不可变结构,我正在尝试创建一个 属性,它 不是 计算值,但它是赋值需要先前分配的属性的值。
(哇一口)
我正在努力的 属性 是 perimeter: Int
// Floor made out of square tiles.
struct Floor {
let
size: (x: Int, y: Int), // How many tiles in the floor
tilePerimeter: Int,
// Calculate entire floor's perimeter based on tile quantity and perimeter:
lazy let perimeter: Int = {
let
t4th = self.tilePerimeter / 4, // Tile width / length
sx = self.size.x * t4th, // All X tiles' length
sy = self.size.y * t4th // All Y tiles' width
return (sx * 2) + (sy * 2) // Perimeter calc
}()
};
不幸的是,Swift 不允许我使用 lazy let
.. 所以我的解决方法是只使用 getter.. 计算 var
。 .但是如果这个计算花费了很长时间(加载图像或复杂的数学)那么它会被调用很多次,而实际上它只需要调用一次一次
所以我的实际解决方法是创建一个初始化程序并在那里分配周长...只有我的一些结构具有许多属性,而不为结构创建初始化程序是 Swiftiness 的一部分我爱的。
我知道我可以将其设为 lazy var
并将结构实例化为 let
,但这似乎令人困惑且容易出错。
有没有一种方法可以保持不变性、性能和 Swiftiness?还有,为什么不允许使用lazy let
?
您可以通过使用默认值为 nil
的可选私有变量来强制仅计算一次,同时仍然使用只读计算变量,这与实现单例对象的方式非常相似。
// Floor made out of square tiles.
struct Floor {
private var computedPerimeter: Int? = nil
let
size: (x: Int, y: Int), // How many tiles in the floor
tilePerimeter: Int
// Calculate entire floor's perimeter based on tile quantity and perimeter:
var perimeter: Int {
mutating get {
if computedPerimeter == nil {
let
t4th = self.tilePerimeter / 4, // Tile width / length
sx = self.size.x * t4th, // All X tiles' length
sy = self.size.y * t4th // All Y tiles' width
computedPerimeter = ((sx * 2) + (sy * 2)) // Perimeter calc
}
return computedPerimeter!
}
}
};
也许你毕竟可以使用 lazy var
:
lazy private(set) var perimeter: Int = {
...
}()
A 只读 var
让您更接近所需的 let
语义。
使用初始化方法:
struct Floor {
let size: (x: Int, y: Int), // How many tiles in the floor
tilePerimeter: Int,
perimeter: Int
init(size:(x: Int, y: Int), tilePerimeter: Int){
self.size = size
self.tilePerimeter = tilePerimeter
// Calculate entire floor's perimeter based on tile quantity and perimeter:
let
t4th = tilePerimeter / 4, // Tile width / length
sx = size.x * t4th, // All X tiles' length
sy = size.y * t4th // All Y tiles' width
self.perimeter = (sx * 2) + (sy * 2) // Perimeter calc
}
}
我有一个正在使用的不可变结构,我正在尝试创建一个 属性,它 不是 计算值,但它是赋值需要先前分配的属性的值。
(哇一口)
我正在努力的 属性 是 perimeter: Int
// Floor made out of square tiles.
struct Floor {
let
size: (x: Int, y: Int), // How many tiles in the floor
tilePerimeter: Int,
// Calculate entire floor's perimeter based on tile quantity and perimeter:
lazy let perimeter: Int = {
let
t4th = self.tilePerimeter / 4, // Tile width / length
sx = self.size.x * t4th, // All X tiles' length
sy = self.size.y * t4th // All Y tiles' width
return (sx * 2) + (sy * 2) // Perimeter calc
}()
};
不幸的是,Swift 不允许我使用 lazy let
.. 所以我的解决方法是只使用 getter.. 计算 var
。 .但是如果这个计算花费了很长时间(加载图像或复杂的数学)那么它会被调用很多次,而实际上它只需要调用一次一次
所以我的实际解决方法是创建一个初始化程序并在那里分配周长...只有我的一些结构具有许多属性,而不为结构创建初始化程序是 Swiftiness 的一部分我爱的。
我知道我可以将其设为 lazy var
并将结构实例化为 let
,但这似乎令人困惑且容易出错。
有没有一种方法可以保持不变性、性能和 Swiftiness?还有,为什么不允许使用lazy let
?
您可以通过使用默认值为 nil
的可选私有变量来强制仅计算一次,同时仍然使用只读计算变量,这与实现单例对象的方式非常相似。
// Floor made out of square tiles.
struct Floor {
private var computedPerimeter: Int? = nil
let
size: (x: Int, y: Int), // How many tiles in the floor
tilePerimeter: Int
// Calculate entire floor's perimeter based on tile quantity and perimeter:
var perimeter: Int {
mutating get {
if computedPerimeter == nil {
let
t4th = self.tilePerimeter / 4, // Tile width / length
sx = self.size.x * t4th, // All X tiles' length
sy = self.size.y * t4th // All Y tiles' width
computedPerimeter = ((sx * 2) + (sy * 2)) // Perimeter calc
}
return computedPerimeter!
}
}
};
也许你毕竟可以使用 lazy var
:
lazy private(set) var perimeter: Int = {
...
}()
A 只读 var
让您更接近所需的 let
语义。
使用初始化方法:
struct Floor {
let size: (x: Int, y: Int), // How many tiles in the floor
tilePerimeter: Int,
perimeter: Int
init(size:(x: Int, y: Int), tilePerimeter: Int){
self.size = size
self.tilePerimeter = tilePerimeter
// Calculate entire floor's perimeter based on tile quantity and perimeter:
let
t4th = tilePerimeter / 4, // Tile width / length
sx = size.x * t4th, // All X tiles' length
sy = size.y * t4th // All Y tiles' width
self.perimeter = (sx * 2) + (sy * 2) // Perimeter calc
}
}