Menu
Coddy logo textTech

外部からの読み取り専用

CoddyのSwiftジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 18/57。

多くの場合、コードの外部からはプロパティを読み取りますが、変更はできないようにします。private(set)はゲッターを通常のレベルに保ち、セッターだけをprivateにします:

struct Counter {
    private(set) var count = 0

    mutating func increment() {
        count += 1
    }
}

var c = Counter()
c.increment()
print(c.count)
// c.count = 99   // エラー: setter は private です

出力:

1

これは、スコアのように、有効な操作によるルールを通じてのみ変更される値に適しています。

class Player {
    let name: String
    private(set) var score = 0
    private(set) var history: [Int] = []

    init(name: String) { self.name = name }

    func award(_ points: Int) {
        guard points > 0 else { return }
        score += points
        history.append(points)
    }
}

let p = Player(name: "Ada")
p.award(10)
p.award(-5)
p.award(3)
print(p.score)
print(p.history)

出力:

13
[10, 3]

インスタンスが存在すると、letプロパティは、その型自身のメソッドを含め、誰にとっても読み取り専用になります。private(set) varは型の内部では変更可能なままです。作成後に決して変更されない値にはletを選びます:

class Order {
    let id: Int                 // 決して変更されない
    private(set) var status = "new"   // 変更されるが、Order内でのみ
    init(id: Int) { self.id = id }
    func ship() { status = "shipped" }
}

読み取り専用の計算プロパティは、変更を許可せずに情報を公開するもう1つの方法です。セッターがまったくないためです。

struct Cart {
    private var prices: [Int] = []
    var total: Int { prices.reduce(0, +) }
    var count: Int { prices.count }

    mutating func add(_ price: Int) { prices.append(price) }
}

var cart = Cart()
cart.add(4)
cart.add(6)
print("\(cart.count) items, total \(cart.total)")

出力:

2 items, total 10
challenge icon

チャレンジ

簡単

Elevator クラスを完成させてください。floor と trips は外部から読み取れますが、クラスによってのみ変更できます(private(set))。goTo(_:) はフロア 0 と topFloor の間を移動します。有効で、異なるフロアへの移動の場合は floor を更新し、trips に 1 を加えて true を返します。無効な移動、または同じフロアへの移動の場合は false を返します。

提供されているコードは最上階を読み取り、その後、移動先のフロアを読み取ります。移動後は floor 3 と出力し、移動が拒否された場合は stay 3 と出力します。最後に、回数とともに trips: を出力します。

コードは Elevator.swift に記述してください。main.swift には提供された入出力コードが含まれており、編集できません。

自分で試してみよう

// 提供された入出力コード: そのままにしておく
var input: [String] = []
while let line = readLine() { input.append(line) }
let lift = Elevator(topFloor: Int(input[0])!)
for line in input.dropFirst() {
    let moved = lift.goTo(Int(line)!)
    print("\(moved ? "floor" : "stay") \(lift.floor)")
}
print("trips: \(lift.trips)")
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Swiftプレイグラウンド