-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
值类型(struct) VS. 引用类型(class) #3
Comments
Swift 中的值类型(Building Better Apps with Value Types in Swift)2019.09.13
1. Reference Semantics
2. Immutablity 是否是一个解决方案?
3. Value Semantics
4. Value Types in Practicesee sample code 5. Mixing value types and reference types5.1 Reference Types Often Contain Value TypesValue types generally used for “primitive” data of objects: class Button : Control {
var label: String
var enabled: Bool
// ...
} 5.2 A Value Type Can Contain a ReferenceCopies of the value type will share the reference: struct ButtonWrapper {
var button: Button
} Maintaining value semantics requires special considerations:
5.3 Immutable References and EquatableReference identity is not enough: struct Image : Drawable {
var topLeft: CGPoint
var image: UIImage
}
extension Image : Equatable {
static func ==(lhs: Image, rhs: Image) -> Bool {
// return lhs.topLeft == rhs.topLeft && lhs.image === rhs.image
return lhs.topLeft == rhs.topLeft && lhs.image.isEqual(rhs.image)
}
}
var image = Image(topLeft: CGPoint(x: 0, y: 0),
image: UIImage(imageNamed:"San Francisco”)!)
var image2 = image
在上面的例子中,image 属性是不可变的引用类型,所以不用担心数据的安全性。但是判断相等性时,不能以引用值是否相等作为依据,而应该将其当做值类型一样根据内容去判断对等性。 5.4 References to Mutable ObjectsUnexpected mutation: struct BezierPath: Drawable {
var path = UIBezierPath()
var isEmpty: Bool {
return path.empty
}
func addLineToPoint(point: CGPoint) {
path.addLineToPoint(point) // Unexpected mutation❌
}
} 在上面的例子中,因为 path 属性是可变的引用类型,所以在 5.5 Copy On Write
struct BezierPath: Drawable {
private var _path = UIBezierPath()
var pathForReading: UIBezierPath {
return _path
}
var pathForWriting: UIBezierPath {
mutating get {
_path = _path.copy() as! UIBezierPath
return _path
}
}
}
extension BezierPath {
var isEmpty: Bool {
return pathForReading.empty
}
mutating func addLineToPoint(point: CGPoint) {
pathForWriting.addLineToPoint(point)
}
}
var path = BezierPath()
var path2 = path
var path2 = path
if path.empty { print("Path is empty") }
var path2 = path
path.addLineToPoint(CGPoint(x: 10, y: 20))
path.addLineToPoint(CGPoint(x: 100, y: 125))
The standard library value types uses this throughout: struct MyWrapper {
var _object: SomeSwiftObject
var objectForWriting: SomeSwiftObject {
mutating get {
if !isKnownUniquelyReferenced(&_object)) {
_object = _object.copy()
}
return _object
}
} } 延伸阅读:
小结
参考 |
Copy on Write
参考: |
No description provided.
The text was updated successfully, but these errors were encountered: