簡體   English   中英

Swift中的只讀和非計算變量屬性

[英]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, setget 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM