2014-09-25 19 views
18

Trong khi chơi một chút với Swift tôi đã cố gắng để viết một tài sản khởi tạo chỉ đọc và lười biếng. Tôi nhanh chóng viết dòng mã đó chỉ để biết rằng nó không được phép.Tài sản chỉ đọc lười biếng trong swift

// no valid Swift code. 
lazy let foo : Int = { return 42 }() 

Bạn phải khai báo thuộc tính lười là var. Cuốn sách nhanh chóng rõ ràng rằng chúng ta hãy có lười biếng không phải là có thể cho một lý do chính đáng:

“Bạn luôn phải khai báo thuộc tính lười biếng như là một biến (với từ khóa var), bởi vì giá trị ban đầu của nó có thể không được lấy ra cho đến khi khởi tạo sau khi hoàn thành. tính liên tục phải luôn luôn có một giá trị trước khởi hoàn tất, và do đó không thể được khai báo là lười biếng.”

Giả sử tôi muốn có một tài sản lười biếng readonly trong nhanh chóng. Whats cách tốt nhất để lưu trữ điều đó là gì?

Trả lời

33

Nếu chỉ đọc và tư nhân là từ đồng nghĩa cho bạn trong trường hợp cụ thể này, sau đó bạn có thể làm cho setter tin bằng cách tuyên bố nó một cách rõ ràng:

private(set) lazy var foo : Int = { return 42 }() 

Đó là một sự thỏa hiệp tốt giữa tính bất biến và lười biếng.

+0

Trình thiết lập riêng tư là đủ cho tôi. Tôi cũng thường sử dụng mẫu đó trong C#. – MBulli

+0

Tôi nghĩ rằng điều này tương đương với '' 'private (set) lazy var foo = 42'''. Nếu bạn đánh dấu setter là private thì không có điểm nào trong việc khai báo getter chỉ với mục đích bỏ qua setter. –

+3

Nó không phải là một getter, nó là một đóng cửa instantiation lười biếng, nhưng nó không phải là cần thiết, hoặc vì nó không chứa bất kỳ logic. Đó là lý do tại sao 'private (set) lazy var foo = 42' sẽ hoạt động giống như vậy. – Danchoys

5

Bạn cũng có thể sử dụng một biến sự ủng hộ tin rằng khởi uể oải:

var foo : Int { return _foo } 
private lazy var _foo :Int = { return 42 }() 
+3

Mặc dù câu trả lời của bạn là chính xác, tôi thích Antonios câu trả lời vì nó không giới thiệu một tài sản khác. – MBulli

+0

Mặc dù câu trả lời được chấp nhận hiện không hoạt động, điều này có tác dụng. – Barry

+0

@Barry câu trả lời được chấp nhận hoạt động ngay bây giờ (như Xcode 7.1) –

2

thể của nó để làm điều này với một tài sản tính và một cấu trúc riêng. Không cần từ khóa lười trên giá trị var tĩnh, khi gán nó kết quả của một khối là hoàn toàn lười biếng.

var foo: Int { 
    struct Holder { 
     static var value = { return 42 }() 
    } 
    return Holder.value 
} 
+0

Đây là thông minh và hữu ích trong một số trường hợp tôi nghĩ, nhưng thật đáng buồn, nó không hữu ích khi giá trị được tính phụ thuộc vào đối tượng "tự" không cho phép các cấu trúc bên trong đóng trên phạm vi bên ngoài. –

+0

@Daniel Bạn thực hiện một điểm tuyệt vời, tuy nhiên cách tiếp cận này hoạt động hoàn hảo trong bối cảnh của câu hỏi. – kevin

Các vấn đề liên quan