Last active
August 29, 2015 14:08
-
-
Save keybuk/2dae7eff37b4e78c77f1 to your computer and use it in GitHub Desktop.
Sub-property Black Magic in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
First we set up a struct, a by-value type: | |
1> struct Point { | |
2. var x, y: Int | |
3. } | |
And we make an array of them: | |
4> var points = [Point]() | |
points: [(Point)] = 0 values | |
5> points.append(Point(x: 0, y: 0)) | |
6> points.append(Point(x: 3, y: 2)) | |
7> points.append(Point(x: 2, y: -1)) | |
8> points.append(Point(x: 3, y: 1)) | |
If we use the a subscript, we can return one of those points structures: | |
9> points[1] | |
$R1: (Point) = { | |
x = 3 | |
y = 2 | |
} | |
We can place it in a new variable, modify it, and see that it doesn't affect the value in the array: | |
10> var point = points[1] | |
point: (Point) = { | |
x = 3 | |
y = 2 | |
} | |
11> point.x = -2 | |
12> point | |
$R3: (Point) = { | |
x = -2 | |
y = 2 | |
} | |
13> points[1] | |
$R4: (Point) = { | |
x = 3 | |
y = 2 | |
} | |
But we if modify the value of x directly through the subscript, it changes the actual array member. | |
14> points[1].x = -2 | |
15> points[1] | |
$R5: (Point) = { | |
x = -2 | |
y = 2 | |
} | |
So this didn't return a new copy of the value, and modify that. Black magic happened and it operated | |
directly on the value referred to by the array. | |
Does the same hold true for custom classes and subscript methods? | |
16> class Line { | |
17. var points = [Point]() | |
18. subscript(i: Int) -> Point { | |
19. get { | |
20. return points[i] | |
21. } | |
22. set { | |
23. points[i] = newValue | |
24. } | |
25. } | |
26. } | |
27> var line = Line() | |
line: Line = { | |
points = 0 values | |
} | |
28> line.points.append(Point(x: 0, y: 0)) | |
29> line.points.append(Point(x: 3, y: 2)) | |
30> line.points.append(Point(x: 2, y: -1)) | |
31> line.points.append(Point(x: 3, y: 1)) | |
Modify a point through a variable: | |
32> line[1] | |
$R6: Point = { | |
x = 3 | |
y = 2 | |
} | |
33> point = line[1] | |
point: Point = { | |
x = 3 | |
y = 2 | |
} | |
34> point.y = 4 | |
35> point | |
$R7: Point = { | |
x = 3 | |
y = 4 | |
} | |
36> line[1] | |
$R8: Point = { | |
x = 3 | |
y = 2 | |
} | |
So that's the same, modifying via a variable only modifies the variable. | |
What about modifying directly through the subscript? | |
37> line[1].x = -1 | |
38> line[1] | |
$R9: Point = { | |
x = -1 | |
y = 2 | |
} | |
Same too. Even though we wrote no special code, and just used "return", somehow the black | |
magic is preserved and we can modify through a subscript. | |
Okay, what about computed properties? | |
39> extension Line { | |
40. var start: Point { | |
41. get { | |
42. return points[0] | |
43. } | |
44. set { | |
45. points[0] = newValue | |
46. } | |
47. } | |
48. } | |
49> line.start | |
$R10: Point = { | |
x = 0 | |
y = 0 | |
} | |
50> line.start.x = 2 | |
51> line.start | |
$R11: Point = { | |
x = 2 | |
y = 0 | |
} | |
Nyaargh! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment