Tại sao tôi không thể sử dụng giao thức let in trong Swift?


80

Tôi nghi ngờ về các giao thức trong Swift về việc sử dụng var và các từ khóa {get set} .

Từ tài liệu của Apple :

Nếu một giao thức yêu cầu một thuộc tính phải có thể tải được và có thể thiết lập, thì yêu cầu thuộc tính đó không thể được đáp ứng bởi một thuộc tính được lưu trữ không đổi hoặc một thuộc tính được tính chỉ đọc. Nếu giao thức chỉ yêu cầu một thuộc tính là có thể nhận được, thì yêu cầu này có thể được đáp ứng bởi bất kỳ loại thuộc tính nào và nó hợp lệ để thuộc tính đó cũng có thể được thiết lập nếu điều này hữu ích cho mã của riêng bạn.

Các yêu cầu thuộc tính luôn được khai báo là thuộc tính biến, được đặt trước từ khóa var. Thuộc tính gettable và có thể thiết lập được biểu thị bằng cách viết {get set} sau khai báo kiểu của chúng và các thuộc tính gettable được chỉ ra bằng cách viết {get}.

Tôi không thể hiểu tại sao tôi không thể sử dụng let . Một var trong giao thức only get không chỉ là let ?

Một cái gì đó như thế này:

protocol someProtocol 
{
   var someProperty: String { get }
}

nó sẽ không chỉ là:

protocol someProtocol 
{
   let someProperty: String
}

Tôi đang thiếu một cái gì đó?


9
thuộc tính gettable vẫn có thể thay đổi giá trị - người triển khai giao thức luôn có thể trả về các giá trị khác nhau, người gọi giao thức đơn giản là không thể đặt chúng. mặt khác, hãy xác định một hằng số. nó chỉ có thể được đặt một lần và không thể có giá trị khác.
pvg

1
@pvg, tại sao bạn không đăng câu trả lời này?
nhã nhặn từ

yup, đây là câu trả lời chính xác ở đây.
sunshinejr

5
@AntonBronnikov Các câu trả lời cho các câu hỏi đơn giản thường kết thúc cuộc cạnh tranh xem ai có thể gõ điều khó hiểu nhất, ít hiểu nhất. Đối với những điều nhỏ, dễ dàng hơn chỉ cần bình luận. Ngoài ra, lười biếng.
pvg

@pvg, tôi hiểu ý bạn. Người ta nên làm đúng.
lịch sự

Câu trả lời:


65

"Một var trong giao thức only get không chỉ là let?" Số A letbiểu thị một hằng số. Nhưng đó không phải là trường hợp ở đây. Hãy xem xét những điều sau:

protocol SomeProtocol {
    var someProperty: String { get }
}

class SomeClass : SomeProtocol {

    var someProperty: String = ""

    func cla () {
        someProperty = "asd"
    }
}

let someInstance = SomeClass()

print(someInstance.someProperty) // outputs ""
someInstance.cla()
print(someInstance.someProperty) // outputs "asd"

Giao thức chỉ định những gì mà lớp phù hợp hiển thị ra bên ngoài - một số thuộc tính của kiểu Stringđược đặt tên somePropertymà bạn ít nhất có thể nhận được.

Nếu giao thức chỉ định { get }thì lớp của bạn có thể chọn tuân theo thông qua let someProperty: String = ""nhưng tương tự nó có thể chọn tuân theo mã trên. Mặt khác, nếu giao thức chỉ định { get set }bạn không thể sử dụng lettrong quá trình triển khai nhưng cũng phải làm cho nó có thể thiết lập.

Một giao thức đơn giản là không thể định nghĩa rằng một giá trị phải không đổi - cũng không nên, đó là một chi tiết triển khai phải được quan tâm (hoặc quyết định về) bởi lớp / cấu trúc thực thi nó.


Nhìn lại thì thấy rất đơn giản và rõ ràng, trong các giao thức chỉ được phép dùng hàm (sau đó là thuộc tính) nhưng tôi luôn thích hỏi và giải quyết mọi nghi ngờ; bây giờ việc sử dụng { get set }nó rõ ràng hơn bao giờ hết, cảm ơn một lần nữa!
Massimo Polimeni

1
Một giao thức đơn giản không thể xác định rằng một giá trị phải không đổi - nó cũng không nên Tại sao không? Tại sao Apple không cung cấp chi tiết hơn và cho phép xác định cả thuộc tính let và var? Hoặc bạn đang nói trong khi Apple có thể đã chọn những gì tôi đã nói, thay vào đó họ đã chọn rằng sự linh hoạt sẽ được cung cấp ở cấp độ triển khai
Honey

46

Sự khác biệt là giữa

protocol MyProtocol {
    let someProperty: String
}

điều này không có ý nghĩa gì - một giao thức không được cho phép chỉ định cách someProperty được định nghĩa / lưu trữ, chỉ nó có sẵn dưới dạng một thuộc tính. Nó có thể là một thuộc tính được tính toán hoặc lưu trữ, nhưng đó là do người triển khai quyết định, không phải bản thân giao thức.

protocol MyProtocol {
    var someProperty: String { get }  // abstract interface
}

struct MyStruct: MyProtocol {
    let someProperty: String  // concrete implementation: stored property
}

struct OtherStruct: MyProtocol {
    let i: Int
    var someProperty: String { return "\(i)" }  // concrete implementation: computed property
}

hoàn toàn được phép!


1
một giao thức không được yêu cầu ra lệnh như thế nào somePropertyđược định nghĩa / lưu trữ Không một giao thức xác định tên biến / loại / phải có thể thiết lập được hay không? Tại sao Apple không cung cấp chi tiết hơn và cho phép xác định cả thuộc tính let và var?
Honey

2

Tôi nghĩ rằng một giao thức có thể yêu cầu cấu trúc phải có một cái gì đó, nhưng nó không thể hạn chế chức năng của cấu trúc hoặc đối tượng. Điều đó sẽ không ngăn cản bạn làm những gì bạn có thể muốn làm trong mã, ví dụ: sử dụng một vartrong giao thức và một letcho việc triển khai được chấp nhận.

protocol MyProtocol {
    var trythis: Int { get }
}

struct MyStructure: MyProtocol {
    let trythis: Int
}
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.