Menu
CoddyTech

Kiểm soát quyền truy cập

Thuộc phần Lập trình hướng đối tượng trong hành trình Swift của Coddy. Bài học 17 trên 57.

Tính đóng gói nghĩa là một kiểu kiểm soát cách sử dụng dữ liệu của nó. Quyền truy cập quyết định ai có thể xem một thuộc tính hoặc phương thức. Đánh dấu một thành viên là private sẽ ẩn thành viên đó khỏi toàn bộ code bên ngoài kiểu (và các phần mở rộng của kiểu đó trong cùng một tệp):

struct Account {
    private var balance = 0

    mutating func deposit(_ amount: Int) {
        balance += amount
    }
}

var a = Account()
a.deposit(50)
// a.balance = 1_000_000   // lỗi: không thể truy cập 'balance' do mức bảo vệ 'private'

Mã bên ngoài chỉ có thể dùng những gì kiểu dữ liệu cung cấp. Kiểu dữ liệu có thể kiểm tra mọi thay đổi, nhờ vậy dữ liệu của nó không bao giờ rơi vào trạng thái mà kiểu dữ liệu không cho phép:

struct Account {
    private var balance = 0

    mutating func deposit(_ amount: Int) {
        if amount > 0 { balance += amount }
    }

    func report() -> String {
        "balance: \(balance)"
    }
}

var a = Account()
a.deposit(50)
a.deposit(-999)
print(a.report())

Đầu ra:

balance: 50

Swift có năm mức truy cập. Nếu không có từ khóa, một thành viên có mức truy cập internal: hiển thị ở mọi nơi trong cùng một module (ứng dụng hoặc package của bạn). Các mức từ mở nhất đến hạn chế nhất:

open        // các module khác có thể sử dụng và tạo lớp con từ đó (chỉ áp dụng cho lớp)
public      // các module khác có thể sử dụng
internal    // mặc định: toàn bộ module
fileprivate // chỉ trong tệp mã nguồn này
private     // chỉ trong kiểu này (và các phần mở rộng của kiểu đó trong tệp)

Các phương thức trợ giúp riêng tư giúp giao diện công khai gọn nhẹ: bên gọi biết kiểu dữ liệu làm gì, chứ không phải cách nó hoạt động.

struct Password {
    private let text: String

    init(_ text: String) { self.text = text }

    var isStrong: Bool {
        hasDigit() && text.count >= 8
    }

    private func hasDigit() -> Bool {
        text.contains { $0.isNumber }
    }
}

print(Password("secret123").isStrong)
print(Password("short1").isStrong)

Đầu ra:

true
false
challenge icon

Thử thách

Dễ

Hoàn thiện struct Locker. code và items là private. store(_:code:) chỉ thêm một món đồ khi mã khớp và trả về kết quả cho biết việc thêm có thành công hay không; items(code:) trả về các món đồ đã lưu, nối bằng , (hoặc empty) khi mã khớp, còn không thì trả về wrong code.

Code được cung cấp đọc mã của tủ khóa, sau đó đọc các lệnh put <code> <item> hoặc open <code>. Với mỗi lệnh put, chương trình in ra stored hoặc denied, còn với mỗi lệnh open, chương trình in ra kết quả tương ứng.

Đặt code của bạn trong Locker.swift. main.swift chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

// Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
var input: [String] = []
while let line = readLine() { input.append(line) }
var locker = Locker(code: input[0])
for cmd in input.dropFirst() {
    let p = cmd.split(separator: " ").map(String.init)
    if p[0] == "put" {
        print(locker.store(p[2], code: p[1]) ? "stored" : "denied")
    } else {
        print(locker.items(code: p[1]))
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Playground Swift