- Hands-On Design Patterns with Swift
- Florent Vilmart Giordano Scalzo Sergio De Simone
- 445字
- 2021-07-02 14:44:58
Struct
Now, let's try to port our Point class into a struct. Consider the following:
struct Point {
var x: Double
var y: Double
}
We have defined a simple struct; as you should notice, there's no need to add a constructor, as the compiler will synthesize it for us:
let point = Point(x: 0.0, y: 0.0)
translate(point: point, dx: 1.0, dy: 1.0)
If we keep the original implementation, our program won't compile. Point is a value type now, and it's forbidden to mutate a value inside of a function! We need to add the inout keyword to indicate that this function will mutate the contents of the value that is passed. When the function returns, the value will be assigned back to the original variable.
With those changes complete, we also need to change our call to indicate that our point variable can be modified by our translate function with the & (ampersand) character. We also need to mark our point as var; otherwise, the inout function cannot modify its contents:
func translate(point: inout Point, dx : Double, dy : Double) {
point.x += dx
point.y += dy
}
var point = Point(x: 0.0, y: 0.0)
translate(&point, dx: 1.0, dy: 1.0)
point.x == 1.0 // true
point.y == 1.0 // true
We've successfully ported this function, but we can do better.
With structs, you will often see that this pattern is cumbersome. We may want the translate function to return a mutated copy of the value we passed in, as follows:
func translate(point: Point, dx : Double, dy : Double) -> Point {
var point = point
translate(point: &point, dx : dx, dy : dy)
return point
}
We'll be able to use the previously defined function with the following code:
let point = Point(x: 0.0, y: 0.0)
let translatedPoint = translate(point, dx: 1.0, dy: 1.0)
point.x == 0.0
point.y == 0.0
translatedPoint.x == 1.0
translatedPoint.y == 1.0
With this new implementation, we're not mutating the value anymore, but the translate function is always returning a new Point value. This has many benefits, including the ability to chain such calls together. Let's add a method to our Point struct:
extension Point {
func translating(dx: Double, dy: Double) -> Point {
return translate(point: self, dx: dx, dy: dy)
}
}
Using our newly crafted extension, we can easily create new Point values and translate them:
let point = Point(x: 0.0, y: 0.0)
.translating(dx : 5.0, dy : 2.0)
.translating(dx : 2.0, dy : 3.0)
point.x == 7.0
point.y == 5.0
- 程序員修煉之道:從小工到專家
- 在你身邊為你設計Ⅲ:騰訊服務設計思維與實戰
- Access 2007數據庫應用上機指導與練習
- 云計算服務保障體系
- R數據科學實戰:工具詳解與案例分析(鮮讀版)
- 大數據Hadoop 3.X分布式處理實戰
- MySQL 8.x從入門到精通(視頻教學版)
- 信息學競賽寶典:數據結構基礎
- 高維數據分析預處理技術
- 云數據中心網絡與SDN:技術架構與實現
- 淘寶、天貓電商數據分析與挖掘實戰(第2版)
- Augmented Reality using Appcelerator Titanium Starter
- Oracle數據庫管理、開發與實踐
- Web Services Testing with soapUI
- 數據庫查詢優化器的藝術:原理解析與SQL性能優化