Swift chỉ đọc thuộc tính bên ngoài, đọc ghi bên trong


103

Trong Swift, cách thông thường để xác định mẫu chung trong đó một thuộc tính là chỉ đọc bên ngoài, nhưng có thể sửa đổi bên trong bởi lớp (và các lớp con) sở hữu nó.

Trong Objective-C, có các tùy chọn sau:

  • Khai báo thuộc tính dưới dạng chỉ đọc trong giao diện và sử dụng phần mở rộng lớp để truy cập thuộc tính nội bộ. Đây là quyền truy cập dựa trên tin nhắn, do đó nó hoạt động tốt với KVO, nguyên tử, v.v.
  • Khai báo thuộc tính là chỉ đọc trong giao diện, nhưng truy cập nội bộ ivar hỗ trợ. Vì quyền truy cập mặc định cho ivar được bảo vệ, điều này hoạt động tốt trong hệ thống phân cấp lớp, nơi các lớp con cũng có thể sửa đổi giá trị, nhưng trường này chỉ đọc.

Trong Java, quy ước là:

  • Khai báo trường được bảo vệ và triển khai (phương thức) công khai, chỉ đọc.

Thành ngữ cho Swift là gì?

Câu trả lời:


219

Với một thuộc tính lớp, bạn có thể chỉ định một cấp độ truy cập khác bằng cách thêm tiền tố khai báo thuộc tính với công cụ sửa đổi quyền truy cập theo sau gethoặc setgiữa dấu ngoặc đơn. Ví dụ, một thuộc tính lớp có bộ thu công cộng và bộ cài đặt riêng sẽ được khai báo là:

private(set) public var readonlyProperty: Int

Đề xuất đọc: Người nhận và Người định cư

Những cân nhắc của Martin về mức trợ năng vẫn còn hiệu lực - tức là không có công cụ protectedsửa đổi, internalchỉ hạn chế quyền truy cập vào mô-đun, chỉ privatevào tệp hiện tại và publickhông có hạn chế.

Swift 3 ghi chú

2 công cụ sửa đổi quyền truy cập mới fileprivateopenđã được thêm vào ngôn ngữ, trong khi privatepublicđã được sửa đổi một chút:

  • openchỉ áp dụng cho lớp và thành viên lớp: nó được sử dụng để cho phép một lớp được phân lớp con hoặc một thành viên được ghi đè bên ngoài mô-đun nơi chúng được định nghĩa. publicthay vào đó, làm cho lớp hoặc thành viên có thể truy cập công khai, nhưng không thể kế thừa hoặc ghi đè

  • privatebây giờ làm cho một thành viên chỉ hiển thị và có thể truy cập được từ khai báo kèm theo, trong khi fileprivatetoàn bộ tệp chứa nó

Thêm chi tiết tại đây .


Đẹp! (Tôi có quyền tự do thêm vartừ khóa bị thiếu để làm cho nó được biên dịch.)
Martin R.

oh cảm ơn rất nhiều :) Tôi thường sao chép từ sân chơi và dán, nhưng lần này có lẽ tôi đã làm sai.
Antonio

10
Lưu ý là Jan-2015 cú pháp này là không hoàn toàn đúng nếu các lớp bên ngoài không phải là public- nó phải được internalhoặc không có gì cả (mặc định là bất cứ lớp học là - publichay internal) - tứcprivate(set) var readonlyProperty: Int
Grimxn

1
Cú pháp là chính xác có tính đến điều đó ngay trước khi mã tôi đã viết một thuộc tính lớp với một getter công khai và một setter riêng tư - nó chỉ là một ví dụ. Nhưng có, công cụ sửa đổi quyền truy cập cho thuộc tính phải "tương thích" với công cụ sửa đổi quyền truy cập lớp / cấu trúc.
Antonio

Về đoạn cuối cùng, tôi đoán điều này đã thay đổi kể từ khi câu trả lời được viết, nhưng privatebây giờ chỉ giới hạn ở khai báo hiện tại (không phải tệp) và fileprivatecó sẵn để hạn chế đối với tệp hiện tại. Cũng publiccó một số hạn chế và opencần thiết để không có hạn chế. Thông tin chi tiết tại đây .
Nigel B. Peck

2

Theo @Antonio, chúng tôi có thể sử dụng một thuộc tính duy nhất để truy cập dưới dạng readOnlygiá trị tài sản công khai và readWriteriêng tư. Dưới đây là hình minh họa của tôi:

class MyClass {

    private(set) public var publicReadOnly: Int = 10

    //as below, we can modify the value within same class which is private access
    func increment() {
        publicReadOnly += 1
    }

    func decrement() {
        publicReadOnly -= 1
    }
}

let object = MyClass()
print("Initial  valule: \(object.publicReadOnly)")

//For below line we get the compile error saying : "Left side of mutating operator isn't mutable: 'publicReadOnly' setter is inaccessible"
//object.publicReadOnly += 1

object.increment()
print("After increment method call: \(object.publicReadOnly)")

object.decrement()
print("After decrement method call: \(object.publicReadOnly)")

Và đây là kết quả:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.