So sánh Reference vs Value Types trong Swift (P1)
Giới thiệu Một trong những lưu ý thay đổi lớn nhất với các nhà phát triển khi chuyển từ Objective-C sang Swift đó là việc mở rộng của Value types (kiểu giá trị) và Reference types (kiểu tham chiếu) Vậy Value types và Reference types là gì? Chúng khác nhau như thế nào? Chúng ta hãy cùng ...
Giới thiệu
Một trong những lưu ý thay đổi lớn nhất với các nhà phát triển khi chuyển từ Objective-C sang Swift đó là việc mở rộng của Value types(kiểu giá trị) và Reference types (kiểu tham chiếu) Vậy Value types và Reference types là gì? Chúng khác nhau như thế nào? Chúng ta hãy cùng tìm hiểu nhé!
Reference Types
Các instance chia sẻ từ một bản copy của dữ liệu và type sử dụng được định nghĩa như là class Trong Objective-C và hầu hết các ngôn ngữ lập trình hướng đối tượng khác, bạn giữ tham chiếu đến đối tượng. Chúng ta quan sát ví dụ sau:
// Reference Types: class Dog { var wasFed = false }
Chúng ta tạo một class Dog, sau đó tạo các instance cho Dog class:
let dog = Dog()
Thêm một object khác để giữ reference tới cùng dog
let puppy = dog
Ở đây dog và puppy trỏ vào cùng một địa chỉ ô nhớ.
Set thức ăn cho vật nuôi bằng cách:
puppy.wasFed = true
Và sau đây là kết quả:
dog.wasFed // true puppy.wasFed // true
Việc thay đổi trong một instance sẽ ảnh hưởng tới những cái khác khi chúng reference chung một object.
Value Types
Mỗi instance giữ một bản copy duy nhất của dữ liệu, thường định nghĩa như: struct, enum hoặc tuple Chúng ta quan sát ví dụ sau:
// Value Types: var a = 42 var b = a b+=1 a // 42 b // 43
Ở đây bạn có thể thấy giá trị của a và b là không giống nhau. Nếu bạn khai báo chúng là kiểu reference types thì cả a và b sẽ cùng là 43 vì chúng cùng trỏ chung vùng địa chỉ ô nhớ.
Tương tự với Cat struct:
struct Cat { var wasFed = false } var cat = Cat() var kitty = cat kitty.wasFed = true cat.wasFed // false kitty.wasFed // true
Mutability (tính thay đổi)
var và let có chức năng khác nhau với reference types và value types
- Với reference types, let nghĩa là reference không thay đổi. Hiểu cách khác là bạn không thể thay đổi references của instance nhưng bạn có thể thay đổi bản thân instance đó.
- Với value types, let nghĩa là instance không thay đổi. Không thuộc tính của instance có thể thay đổi được, bất kể nó được khai báo là let hoặc var. => Dễ dàng control sự thay đổi với value types hơn.
Which to Use and When (sử dụng ở đâu và khi nào)
Bây giờ bạn đã biết sự khác nhau giữa hai loại, vậy khi nào bạn nên sử dụng chúng?
When to Use a Value Type
Chúng ta sử dụng value types trong những trường hợp sau:
- So sánh instance data với "=="
struct Point: CustomStringConvertible { var x: Float var y: Float var description: String { return "{x: (x), y: (y)}" } }
let point1 = Point(x: 2, y: 3) let point2 = Point(x: 2, y: 3)
Dưới đây ví dụ thực hiện so sánh "=="
extension Point: Equatable { } func ==(lhs: Point, rhs: Point) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y }
- Bạn muốn bản sao có trạng thái độc lập
struct Shape { var center: Point } let initialPoint = Point(x: 0, y: 0) let circle = Shape(center: initialPoint) var square = Shape(center: initialPoint)
- Dữ liệu sẽ được sử dụng trong code trên nhiều threads Việc đảm bảo dữ liệu của bạn có thể truy cập trên nhiều threads và equal trên các threads, bạn có thể sử dụng reference type và thực hiện locking(không hề đơn giản) Nếu mỗi thread có thể sở hữu dữ liệu riêng thì sử dụng value types sẽ giảm sự tranh luận vì mỗi chủ của dữ liệu sở hữu bản sao duy nhất chứ k phải dùng chung.
When to Use a Reference Type
- So sánh instance identity với "==="
- Bạn muốn tạo trạng thái chia sẻ, có thể thay đổi.
Đôi khi bạn muốn một phần dữ liệu được lưu trữ như là một instance và được truy cập và biến đổi bởi nhiều người tiêu dùng. Một đối tượng thông thường với trạng thái chia sẻ, có thể thay đổi là một tài khoản ngân hàng được chia sẻ. Bạn có thể thực hiện một đại diện cơ bản của một tài khoản và người như sau:
class Account { var balance = 0.0 } class Person { let account: Account init(_ account: Account) { self.account = account } }
let account = Account() let person1 = Person(account) let person2 = Person(account) person2.account.balance += 100.0 person1.account.balance // 100 person2.account.balance // 100
Kết Luận
Bài viết "So sánh Reference vs Value Types trong Swift" gồm 2 phần. Trong phần một này, chúng ta đã tìm hiểu về khái niệm của từng loại, sự khác nhau giữa chúng. Trong phần tiếp theo, chúng ta sẽ cùng đi tìm hiểu sâu hơn về từng loại, cũng như sử dụng chúng trong các project thực tế như thế nào. Cám ơn bạn đã dành thời gian cho bài viết!