Menu

Category

Archive

logo


The Swift Programming Language ~ Properties [Observers & Type Properties]

2014-06-17 13:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、前回 の続きの Properties に関して。

Properties

プロパティは、クラス、構造体、Enumeration に関連した値です。Swift では、下記で説明するようにいくつかの種類のプロパティがあります。この記事は、Property Observers と Type Properties に関して。

5. Property Observers

Property Observers はプロパティの値が変更される際に、ある処理をしたい場合に使用します。どの Stored Properties にも Property Observers を追加することができます。また、継承したプロパティなら、Stored Properties にも Computed Properties にも追加できます。

Property Observers には、2 つのタイプがあります。1 つ目は、willSet。プロパティの値が変更される前に呼ばれるもの。そして、2 つ目が、didSet。プロパティが変更された後に呼ばれるものです。willSetは、新しいこれからセットされる値をコンスタント引数として受け取り、それを処理の中で使用できます。また、didSetは、新しい値がセットされる前の古い値をコンスタントとして使用できます。

この Property Observers は、プロパティが初期化される際には呼ばれません。あくまで、プロパティが変更される際に、呼ばれるものです。しかし、新しい値と古い値が同じ値でも、これらの Observers は呼ばれます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            println("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                println("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps

上記の willSetdidSet の実装方法は多少違いがあります。willSet は、新しい値である引数の名前を自分で指定しています。この例では、newTotalSteps です。そして、この newTotalSteps を println() の中で使用しています。もし、この名前を自分で指定しなかった場合、newValue という名前を処理の中で使用できます。didSet は引数の名前を指定していません。自動的に割り当てられる oldValue という引数名を使用して処理をしています。もちろん、willSet と同じように自分で引数の名前を指定することもできます。

6. Type Properties

今まで見てきたプロパティは、インスタンスに属するプロパティでした。それに加えて、タイプ(クラス、構造体、Enumeration)に属する Type Properties というものを作成することもできます。これは、各タイプのすべてのインスタンスにおいて共通の値を定義するのに向いています。構造体と Enumeration に対しては、stored と comuted Type Properties を使用できます。クラスに対しては、computed Type Properties のみ使用できます。構造体と Enumeration にて使用できる Stored Type Properties は、変数でもコンスタントでも可能です。また、stored Type Properties には、常にデフォルト値を設定しなければなりません。

Type Propertiesを宣言する方法は、、構造体と Enumeration の Type Properties には、static キーワードを使用します。クラスの Type Properties には、class キーワードを使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
    // return an Int value here
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
    // return an Int value here
    }
}
class SomeClass {
    class var computedTypeProperty: Int {
    // return an Int value here
    }
}

この例では、Computed Properties においてゲッターしか設定していませんが、Computed Properties と同じようにゲッターセッター両方使用できます。

Enumeration には、Stored Properties を使用できないので、static を除き、Stored Properties (インスタンスプロパティ) を作成しようとするとエラーになります。Computed Properties は使用できるので、static を除き、Computed Properties として使用しても問題ありません。

1
2
3
4
5
6
7
enum SomeEnumTest {
    var storedTypeProperty = "Some value." // err : No Stored Properties for enum
    var computedTypeProperty: Int { // OK : YES Computed Properties for enum
        return 42
    }
    Case Test
}

このように使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
println(SomeClass.computedTypeProperty)
// prints "42"
 
println(SomeStructure.storedTypeProperty)
// prints "Some value."

SomeStructure.storedTypeProperty = "Another value."
println(SomeStructure.storedTypeProperty)
// prints "Another value."

var some = SomeEnumTest.Test
println("Hi, \(some.computedTypeProperty)")
// prints "Hi, 42" ( add static before var storedTypeProperty to test )