Struct là một kiểu giá trị (value type) trong ngôn ngữ Swift, các thể hiện của nó được sao chép khi truyền giữa các phần của mã. Không giống như lớp, cấu trúc không hỗ trợ kế thừa, nhưng chúng triển khai giao thức, chứa thuộc tính và phương thức, và cung cấp quản lý bộ nhớ có thể dự đoán mà không cần ARC. Theo Swift Programming Language Guide, 2026, struct là khối xây dựng cơ bản của Swift — ngay cả các kiểu chuẩn Int, String, Array và Dictionary cũng được triển khai dưới dạng cấu trúc. Ngôn ngữ này khuyến nghị cấu trúc là lựa chọn ưu tiên cho mô hình hóa dữ liệu.
Các điểm chính
Struct (cấu trúc) là một kiểu dữ liệu tổng hợp trong Swift nhóm các thuộc tính và phương thức liên quan thành một thực thể duy nhất. Không giống như lớp, cấu trúc là value types: khi được truyền vào hàm hoặc gán cho biến mới, một bản sao độc lập của cấu trúc được tạo ra, không phải tham chiếu đến đối tượng gốc.
Swift sử dụng cấu trúc cho tất cả kiểu nguyên thủy: Int, Double, String, Bool, Array, Dictionary và Set. Điều này có nghĩa là ngay cả một Int cơ bản cũng hoạt động như một cấu trúc — một bản sao được tạo ra khi gán. Nhà phát triển có thể định nghĩa cấu trúc riêng với bất kỳ tập hợp thuộc tính và phương thức nào.
Theo Swift Evolution (SE-0143), quyết định triển khai các kiểu chuẩn dưới dạng cấu trúc được thúc đẩy bởi hiệu suất và khả năng dự đoán. Value types không tạo vòng lặp tham chiếu, không yêu cầu đếm tham chiếu ARC và đảm bảo rằng việc sửa đổi bản sao sẽ không ảnh hưởng đến bản gốc — điều này cực kỳ quan trọng cho tính bất biến của dữ liệu trong các tình huống đa luồng.
Ngữ nghĩa value type là sự khác biệt chính giữa struct và class. Khi bạn gán một cấu trúc cho biến mới hoặc truyền nó vào hàm, Swift tạo một bản sao độc lập của tất cả dữ liệu. Mọi thay đổi trong bản sao không ảnh hưởng đến bản gốc, loại bỏ các tác dụng phụ điển hình của kiểu tham chiếu.
// Ví dụ về ngữ nghĩa value type
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // p2 là bản sao độc lập của p1
p2.x = 99 // Chỉ p2 thay đổi
print(p1.x) // 10 — p1 không thay đổi
print(p2.x) // 99
Swift sử dụng Copy-on-Write (COW) để tối ưu hóa việc sao chép. Nếu nhiều biến tham chiếu đến cùng một cấu trúc nhưng không biến nào sửa đổi dữ liệu, sẽ không có bản sao thực tế nào xảy ra. Swift chia sẻ bộ nhớ giữa các biến cho đến lần thay đổi đầu tiên — sau đó một bản sao thực sự được tạo ra. Điều này ngăn chặn các thao tác cấp phát quá mức và tăng tốc làm việc với bộ sưu tập.
Theo mặc định, các phương thức của cấu trúc không thể sửa đổi thuộc tính của nó — Swift yêu cầu từ khóa mutating rõ ràng cho các phương thức thực hiện thay đổi. Hạn chế này bảo vệ khỏi sự thay đổi ngẫu nhiên và làm cho mã có thể dự đoán: nếu một phương thức không được đánh dấu là mutating, bạn được đảm bảo sẽ không thay đổi cấu trúc.
Khi bạn thêm từ khóa mutating trước một phương thức, Swift có khả năng ghi các giá trị mới vào thuộc tính của cấu trúc. Trên thực tế, phương thức thậm chí có thể thay thế hoàn toàn thể hiện cấu trúc bằng một thể hiện mới thông qua self =. Cơ chế này được sử dụng, ví dụ, trong các kiểu Option và Result.
// Struct với phương thức mutating
struct Counter {
private var value: Int = 0
// Phương thức mutating — có thể sửa đổi thuộc tính
mutating func increment() {
value += 1
}
// Phương thức mutating có thể thay thế hoàn toàn self
mutating func reset() {
self = Counter()
}
// Phương thức non-mutating — chỉ đọc
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // 1
counter.reset()
print(counter.currentValue()) // 0
Quy tắc cho mutating: cấu trúc phải được khai báo với var, không phải let — một cấu trúc hằng không thể gọi phương thức mutating. Trình biên dịch kiểm tra điều này tại thời điểm xây dựng: cố gắng gọi phương thức mutating trên hằng let sẽ dẫn đến lỗi biên dịch.
Sự lựa chọn giữa struct và class là một trong những quyết định cơ bản trong Swift. Cả hai kiểu đều có thể chứa thuộc tính, phương thức, bộ khởi tạo và triển khai giao thức, nhưng có sự khác biệt cơ bản về ngữ nghĩa bộ nhớ, kế thừa và quản lý vòng đời.
| Đặc điểm | struct | class |
|---|---|---|
| Kiểu | Value type (sao chép) | Reference type (tham chiếu) |
| Kế thừa | Không hỗ trợ | Hỗ trợ |
| ARC / đếm tham chiếu | Không yêu cầu | ARC yêu cầu |
| Hủy khởi tạo | Không hỗ trợ | Hỗ trợ deinit |
| Sửa đổi thuộc tính trong hằng | Chỉ qua var | Có thể qua let (tham chiếu là hằng) |
| Ép kiểu | Không hỗ trợ | Hỗ trợ |
| Lưu trữ trong bộ sưu tập | Lưu trực tiếp (giá trị) | Lưu dưới dạng tham chiếu (con trỏ) |
Cấu trúc được ưa chuộng khi dữ liệu không yêu cầu kế thừa, không nên có danh tính chia sẻ (ví dụ: tọa độ, kích thước, cấu hình) và được truyền giữa các mô-đun. Lớp được chọn cho các thành phần UI (UIView, UIViewController), singleton và các đối tượng có danh tính chia sẻ.
Apple khuyến nghị sử dụng struct như kiểu mặc định cho mô hình hóa dữ liệu trong Swift. Cấu trúc phù hợp với hầu hết các tình huống nhờ ngữ nghĩa sao chép có thể dự đoán và không có chi phí đếm tham chiếu. Hãy xem các trường hợp điển hình khi struct là lựa chọn tối ưu.
Nếu một thực thể chứa dữ liệu không cần kế thừa (Product, User, Order, Point), hãy sử dụng struct. Trình biên dịch tự động tạo memberwise initializer — bạn không cần viết init thủ công. Equatable và Hashable cũng được tự động triển khai cho các cấu trúc có tất cả thuộc tính tuân thủ các giao thức này.
Cho cấu hình, cài đặt và cờ không thay đổi sau khi tạo, struct tốt hơn class. Một cấu trúc hằng (let) đảm bảo tính bất biến của tất cả các trường lồng nhau — trong class, điều này chỉ áp dụng cho tham chiếu, không phải nội dung của đối tượng.
Cấu trúc an toàn trong môi trường đa luồng nhờ ngữ nghĩa giá trị. Mỗi luồng nhận được một bản sao độc lập của dữ liệu và không ảnh hưởng đến các luồng khác. Điều kiện đua giữa các luồng là không thể đối với value types, làm cho struct trở thành lựa chọn ưa chuộng cho các mô hình trong SwiftUI (ObservableObject yêu cầu class, nhưng @State sử dụng struct).
// Ví dụ sử dụng struct cho mô hình dữ liệu
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// Thuộc tính tính toán — non-mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// Trình khởi tạo memberwise tự động
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// Sao chép an toàn cho đa luồng
var userCopy = user
userCopy.isPremium = false
// user.isPremium vẫn là true
Sử dụng class khi bạn cần kế thừa (các thành phần UIKit/AppKit), danh tính chia sẻ (delegate, observer) hoặc vòng đời đối tượng được kiểm soát (deinit). Mọi thứ khác — hãy sử dụng struct.
Câu hỏi thường gặp
Struct trong Swift là kiểu giá trị được sao chép khi truyền giữa các phần của mã. Cấu trúc có thể chứa thuộc tính, phương thức, bộ khởi tạo và triển khai giao thức. Các kiểu cơ bản của Swift (Int, String, Array) được triển khai dưới dạng cấu trúc.
Struct là value type (sao chép khi gán), không hỗ trợ kế thừa và không yêu cầu ARC. Class là reference type (truyền theo tham chiếu), hỗ trợ kế thừa, hủy khởi tạo và đếm tham chiếu. Các nhà phát triển khuyến nghị struct là kiểu mặc định.
Mutating là từ khóa chỉ ra rằng phương thức của cấu trúc có thể sửa đổi thuộc tính của nó. Không có mutating, trình biên dịch cấm sửa đổi trường. Phương thức mutating chỉ có thể được gọi trên các biến khai báo với var, không phải let.
Copy-on-Write (COW) là tối ưu hóa của Swift cho cấu trúc trong đó việc sao chép dữ liệu thực tế được hoãn lại cho đến lần thay đổi đầu tiên. Miễn là tất cả các biến chỉ đọc cấu trúc, chúng chia sẻ một vùng bộ nhớ duy nhất. Điều này cải thiện hiệu suất khi làm việc với các bộ sưu tập lớn.
Sử dụng struct cho mô hình dữ liệu không cần kế thừa, cấu hình, DTO và tình huống đa luồng. Sử dụng class cho các thành phần UI UIKit/AppKit, singleton, thực thể có danh tính chia sẻ (delegate, observer) và đối tượng cần hủy khởi tạo.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm