I wanted to change my code to use lazy
variable instead of Computed property.
this code works
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 10.0, height = 10.0
}
struct Rect {
var origin = Point()
var size = Size()
var center: Point{
get{
let centerX = origin.x (size.width / 2)
let centerY = origin.y (size.height / 2)
return Point(x: centerX, y: centerY)
}
}}
let shape = Rect()
print(shape.center)
But this code produces an error
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 10.0, height = 10.0
}
struct Rect {
var origin = Point()
var size = Size()
lazy var center = Point(x: origin.x (size.width / 2), y: origin.y (size.height / 2))
}
let shape = Rect()
print(shape.center)
I can fix the error if I changed let shape = Rect()
to variable type var shape = Rect()
OR when I change Rect
to class instead of struct
What is wrong with my code and why does it give me error?
CodePudding user response:
Notice that getting a lazy property potentially changes the struct value. Its state could change from "the lazy property has not been computed" to "the lazy property has been computed". This is why the getters of lazy properties are mutating
.
A let
constant does not allow its value to change, so you can't use mutating
members on it. var
s do, so that's why using a var
makes your code compile.
Changing Rect
to a class makes it a reference type. This means that the let
constant shape
stores a reference to an instance of Rect
, and this reference cannot be changed (e.g. you can't do shape = someOtherRect
afterwards). However, the instance of Rect
can still be changed (remember that the let
constant is only storing a reference to it), and so getting a lazy property is fine on shape
, when Rect
is a class. Doing this will only potentially change the instance of Rect
.
In my opinion, it is not appropriate to change Rect.center
to a lazy property. After the first use of its getter, center
will stay unchanged even if you change origin
or size
:
var shape = Rect()
print(shape.center)
shape.size = Size(width: 100, height: 100)
// now shape.center is incorrect!