[英]Read-only and non-computed variable properties in Swift
我正在嘗試使用新的Apple Swift語言來解決問題。 假設我曾經在Objective-C中做過類似的事情。 我有readonly
屬性,他們不能單獨更改。 但是,使用特定方法,屬性會以邏輯方式更改。
我采用以下示例,一個非常簡單的時鍾。 我會在Objective-C中寫這個。
@interface Clock : NSObject
@property (readonly) NSUInteger hours;
@property (readonly) NSUInteger minutes;
@property (readonly) NSUInteger seconds;
- (void)incrementSeconds;
@end
@implementation Clock
- (void)incrementSeconds {
_seconds++;
if (_seconds == 60) {
_seconds = 0;
_minutes++;
if (_minutes == 60) {
_minutes = 0;
_hours++;
}
}
}
@end
出於特定目的,我們不能直接觸摸秒,分和小時,並且只允許使用方法逐秒遞增。 只有這種方法可以通過使用實例變量的技巧來更改值。
由於Swift中沒有這樣的東西,我試圖找到一個等價物。 如果我這樣做:
class Clock : NSObject {
var hours: UInt = 0
var minutes: UInt = 0
var seconds: UInt = 0
func incrementSeconds() {
self.seconds++
if self.seconds == 60 {
self.seconds = 0
self.minutes++
if self.minutes == 60 {
self.minutes = 0
self.hours++
}
}
}
}
這可行,但任何人都可以直接改變屬性。
也許我已經在Objective-C中設計了一個糟糕的設計,這就是為什么潛在的新Swift等價物沒有意義。 如果沒有,如果有人有答案,我將非常感激;)
也許Apple承諾的未來訪問控制機制就是答案?
謝謝!
只需在屬性聲明前加上private(set)
,如下所示:
public private(set) var hours: UInt = 0
public private(set) var minutes: UInt = 0
public private(set) var seconds: UInt = 0
private
將其保存在源文件的本地,而internal
將其保留在模塊/項目的本地。
private(set)
創建一個read-only
屬性,而private
設置both, set
和get
to private。
做你想做的事有兩種基本方法。 第一種方法是擁有一個私有屬性和一個返回該屬性的公共計算屬性:
public class Clock {
private var _hours = 0
public var hours: UInt {
return _hours
}
}
但是,這可以通過“The Swift Programming Language”一書的“訪問控制”一節中所述的不同的,更短的方式實現:
public class Clock {
public private(set) var hours = 0
}
作為旁注,您必須在聲明公共類型時提供公共初始化程序。 即使您為所有屬性提供默認值, init()
必須明確定義為public:
public class Clock {
public private(set) var hours = 0
public init() {
hours = 0
}
// or simply `public init() {}`
}
在討論默認初始化程序時,本書的相同部分也對此進行了解釋。
由於沒有訪問控制(意味着您無法根據呼叫者的身份制定不同的訪問合同),以下是我現在要做的事情:
class Clock {
struct Counter {
var hours = 0;
var minutes = 0;
var seconds = 0;
mutating func inc () {
if ++seconds >= 60 {
seconds = 0
if ++minutes >= 60 {
minutes = 0
++hours
}
}
}
}
var counter = Counter()
var hours : Int { return counter.hours }
var minutes : Int { return counter.minutes }
var seconds : Int { return counter.seconds }
func incrementTime () { self.counter.inc() }
}
這僅僅增加了直接訪問計數器的間接級別; 另一個類可以制作一個Clock然后直接訪問它的計數器。 但是這個想法 - 即我們試圖達成的合同 - 是另一個類應該只使用Clock的頂級屬性和方法。 我們不能強制執行該合同,但實際上在Objective-C中實施也幾乎是不可能的。
實際上,訪問控制(在Swift中尚不存在)並不像您在Objective C中想象的那樣強制執行。如果他們真的想要,人們可以直接修改您的只讀變量。 他們只是不使用該類的公共接口。
您可以在Swift中執行類似的操作(剪切和粘貼代碼,加上一些修改,我沒有測試它):
class Clock : NSObject {
var _hours: UInt = 0
var _minutes: UInt = 0
var _seconds: UInt = 0
var hours: UInt {
get {
return _hours
}
}
var minutes: UInt {
get {
return _minutes
}
}
var seconds: UInt {
get {
return _seconds
}
}
func incrementSeconds() {
self._seconds++
if self._seconds == 60 {
self._seconds = 0
self._minutes++
if self._minutes == 60 {
self._minutes = 0
self._hours++
}
}
}
}
除了實際存儲的屬性在公共接口中可見之外,它與Objective C中的相同。
在swift中你也可以做一些更有趣的事情,你也可以在Objective C中做,但它在swift中可能更漂亮(在瀏覽器中編輯,我沒有測試它):
class Clock : NSObject {
var hours: UInt = 0
var minutes: UInt {
didSet {
hours += minutes / 60
minutes %= 60
}
}
var seconds: UInt {
didSet {
minutes += seconds / 60
seconds %= 60
}
}
// you do not really need this any more
func incrementSeconds() {
seconds++
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.