Variation method
Last time we saw that both classes and structs in Swift can define methods. One difference, however, is that by default, a value type attribute cannot be modified by its own instance method.
The struct self is immutable because it is a value type immutable.
If you want to modify the mutating keyword.
Struct Point {var x = 0.0, y = 0.0 mutating func moveBy(x deltaX: Double, y deltaY: Double) { self.x += deltaX self.y += deltaY } }Copy the code
What does mutating do? Add the following code
Struct Point {var x = 0.0, y = 0.0 mutating func moveBy(x deltaX: Double, y deltaY: Double) { x += deltaX y += deltaY } func moveByTest(x deltaX: Double, y deltaY: Double) { print("--\(self.x)") print("--\(self.x)") } }Copy the code
After compiling SIL, we look at the SIL file and see the following differences between moveBy and moveByTest:
// Point.moveBy(x:y:)
sil hidden @$s4main5PointV6moveBy1x1yySd_SdtF : $@convention(method) (Double, Double, @inout Point) -> ()
// Point.moveByTest(x:y:)
sil hidden @$s4main5PointV10moveByTest1x1yySd_SdtF : $@convention(method) (Double, Double, Point) -> ()
Copy the code
MoveBy and moveByTest have the same arguments, except that the mutating keyword is added to moveBy, and the @inout flag is added to moveByTest.
An @inout parameter is indirect. The address must be of An initialized object. The current parameter type is indirect, passing An already initialized address.
The nature of mutating methods: For mutating methods, the passed self is marked as an inout parameter. Whatever happens inside the mutating method affects everything about the external dependency type.
Input and output parameters:
If we want a function to be able to change the value of a formal parameter, and we want those changes to persist after the function ends, we need to define formal parameters as input and output formal parameters. Adding an inout keyword at the beginning of the formal parameter definition defines an input/output formal parameter
As explained above, we implement a mutating method ourselves using the inout keyword as follows:
Struct Point {var x = 0.0, y = 0.0 mutating func moveBy(x deltaX: Double, y deltaY: Double) { x += deltaX y += deltaY } func moveByTest(x deltaX: Double, y deltaY: Double) { print("--\(self.x)") print("--\(self.x)") } func inoutTest(value: Double, point: inout Point) { point.x += value } } var p1 = Point() var x1:Double = 100 p1.inoutTest(value: x1, point: &p1) print(p1.xCopy the code
Finally, let’s do a problem set:
var p = Point() let xx1 = p var xx2 = withUnsafePointer(to: &p){ return $0 } var xx3 = p p.x = 999 print("xx1 = \(xx1.x)") print("xx2 = \(xx2.pointee.x)") print("xx3 = \(xx3.x)") Output xx1 = 0.0 / / xx1 is another value constants, and p = 999.0 / / it doesn't matter the xx2 xx2 memory pointer and p, p, is to modify the xx2 xx3 = 0.0 / / xx3 for deep copy assignment, a new stack memory, and p it doesn't matterCopy the code