The Swift Programming Language - Properties（プロパティ）をまとめる


[The Swift Programming Language をまとめるトップ](http://qiita.com/kiyotaman/items/052f82e9f93590b79c64)

## Properties（プロパティ）

プロパティはクラスや構造体や列挙型に値を紐づける役割がある
定数や変数をそのインスタンスの一部として保持する
算出された(setter, getter)算出プロパティは値を保存するるというより計算する

算出(setter, getter)される算出プロパティはクラスや構造体や列挙型にある
値保存する保存型プロパティはクラスと構造体にある

算出と保存プロパティは特定の型のインスタスと紐づく
タイププロパティはそれ自体とも紐づく

プロパティオブザーバー定義してプロパティの変更を監視することができる
カスタムアクションに返答することができる

自分で定義した保存プロパティをオブザーバーに追加すこともできる
スパークラスから継承することもできる

以下、下記をみたほうがわかりやすい

Initialization の章でも他の解説があると思う


### Stored Properties（保持型プロパティ）
あるクラスや構造体のインスタスの一部としてある定数や変数が保持型プロパティ
保持型プロパティには初期値を設定することができる

初期化中に初期値を修正することもできる
初期化中に初期値が指定された定数として定義されたプロパティも値変更することができる

```swifg
struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 初期化時に値を指定する事ができる
// length は定数なので一度セットしたら変更ができくなる
rangeOfThreeItems.firstValue = 6
// firstValue は変数なので、後ででも変更することができる
```

### Stored Properties of Constant Structure Instances（定数型インスタンスの保持型プロパティ）

以下の様に _rangeOfFourItem_ を定数で宣言すると変数で宣言してあるプロパティも変更できなくなる

```swift
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// let を使って定数でインスタンスを宣言
// (error) rangeOfFourItems.firstValue = 6
// 定数で宣言されているので、変数プロパティも変更不可
// 上記はエラーとなる
```

値型なので構造体が定数としてインスタンスが定義された場合、全てのプロパティが定数として扱われる
クラスなどの参照型の場合は異なる
参照がたの場合、定数で宣言しても初期化された変数型のプロパティ値はインスタンス経由で変更できる

#### Lazy Stored Properties（動的に生成される保持型プロパティ）
##### @lazy
_@lazy_ をプロパティンの前に付けると、そのプロパティにアクセスされた時にプロパティへの定義が実際に呼ばれる

**_@lazy_ を付ける時は必ず _変数(var)_ で宣言する必要がある**

```swift
class DataImporter {
/*
別ファイルからデータを取り込むクラス
*/
    var fileName = "data.txt"
// データーをインポートする関数をつらつら
}

class DataManager {
    @lazy var importer = DataImporter()
    var data = String[]()
    // インポートしたデータをマネージするクラス
}
let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// この時点で _importer_ プロパティはまだ作成されていない

println(manager.importer.fileName)
// この時点で_importer_ プロパティが生成させる
// prints "data.txt"

```

場合によっては不必要なメモリーを消費しないですむ

#### Stored Properties and Instance Variables（保持型プロパティとインスタス値）
ObjCにもある様に値と参照元（valuesとreferences）をクラスのインスタンスの一部として保持するという二つの方法がある
更に、プロパティに保存された値のバッキングストア（裏で保持する）としてインスタンス値を利用する

Swiftはこれらのコンセプトをシングルプロパティ定義とし統合している
プロパティは一致するインスタンスの値を保持しない
バッキングストアはプロパティに直接アクセスしない
どのように違うコンテキストから値にアクセスすかの混乱を防ぐ
プロパティの宣言も一つに整理されたり分かりやすくまとまるようになる
全ての情報がプロパティを一カ所で定義できるようになる

### Computed Properties（算出プロパティ）
クラスと構造体と列挙型は値を保持しない算出プロパティを指定できる
間接的に、settr、getter を使ってその他のプロパティの値をセットしたり取得したりする
値が確定していないので、算出プロパティは必ず変数として宣言する

以下の様に書ける

```swift
struct Point {
	var x = 0.0, y = 0.0
}

struct Size {
	var width = 0.0, height = 0.0
}

struct Rect {	
	var origin = Point()
	var size = Size()
	var center: Point {
	get {
		let centerX = origin.x + (size.width / 2)
		let centerY = origin.y + (size.height / 2)
		return Point(x: centerX, y: centerY)
	}
	set(newCenter) {
		origin.x = newCenter.x - (size.width / 2)
		origin.y = newCenter.y - (size.height / 2)
	}
	}
}
var square = Rect(
var square = Rect(
    origin: Point(x: 0.0, y: 0.0),
    size: Size(width: 10.0, height: 10.0)
    )
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
println("square.origin は (\(square.origin.x), \(square.origin.y))")
// prints "square.origin は (10.0, 10.0)"
```

#### Shorthand Setter Declaration（Setter宣言簡略書式）
##### newValue
初期の値の名前に _newValue_　が自動でセットされる
以下が簡略書式

```swift
struct AlternativeRect {
	var origin = Point()
	var size = Size()	
	var center: Point {
	get {
		let centerX = origin.x + (size.width / 2)
		let centerY = origin.y + (size.height / 2)
		return Point(x: centerX, y: centerY)
	}
	set {
		origin.x = newValue.x - (size.width / 2)
		origin.y = newValue.y - (size.height / 2)
	}
	}
}
```

#### Read-Only Computed Properties（読み専用算出プロパティ）
_set_  を使わないで、 _get_ だけ準備すると読み取り専用のプロパティになる

> **NOTE**
読み専用でも変数として宣言する

##### return
_get_　を書かないで _return_ だけ書いて簡略化できる

```swift
struct Cuboid {
	var width = 0.0, height = 0.0, depth = 0.0
	var volume: Double {
	return width * height * depth
	}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// prints "the volume of fourByFiveByTwo is 40.0"
```

### Property Observers（プロパティの監視）
プロパティの監視はプロパティの更新に応答する
オブザーバーは値がセットされるときに走る
接する値とセットされた値が同じでも走る

オブザーバーは _@lazy_ 以外の保存型プロパティに定義できる
サブクラス化してオーバーライドしたプロパティにも定義できる

> **NOTE**
算出プロパティは set があるのでそこで監視できるのでこの機能は必要ない

#### willSet
値が保存される直前に呼ばれる

#### didSet
値が保存された直後に呼ばれる

#### oldValue
didSet にセット前の値として _oldValue_ を使ってアクセスできる

```swift
class StepCounter {
	var totalSteps: Int = 0 {
	willSet(newTotalSteps) {
		println("totalSteps に \(newTotalSteps) を加える")
	}
	didSet {
		if totalSteps > oldValue {
			println("\(totalSteps - oldValue) ステップ追加")
		}
	}
	}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// prints "totalSteps に 200 を加える"
// prints "200 ステップ追加"
stepCounter.totalSteps = 360
// prints "totalSteps に 360 を加える"
// prints "160 ステップ追加"
```

### Global and Local Variables （クローバルとローカル変数）
算出プロパティと監視されているプロパティはグローバルやローカル変数として有効
グローバル変数は、関数、メソッド、クロージャーなど外側で定義されたもので、ソーカルはその逆

### Type Properties（タイププロパティ）
インスタンスプロパティは特定の型のインスタンスに属するプロパティ
インスタンスを新たに生成するたびに独立したものになる

型それ自身に所属するプロパティも定義することができる
インスタスを定義せず、例えば、```someClass.someTypeProperty``` のように、クラス名.プロパティ名とドットで繋いでアクセスできる

複数のインスタンスを生成しても、型プロパティの値は共通したコンスタントなプロパティとして参照できる
C言語の static const に近い

_set_ や _get_ 算出型も定義できる

構造体と列挙型は保存型と算出型プロパティを設定できる
クラスは算出型にのみ型プロパティを定義できる
保存型は定数と変数、算出型は変数のみ設定可能

> **NOTE**
保存型とは異なりイニシャライザーが走らないので、必ず初期値をしていする必要がある

#### Type Property Syntax（タイププロパティシンタックス）
タイププロパティはその型の中にある

#### static
構造体や列挙型の場合に用いる
保存型、算出型両方定義可能

#### class
class の時に用いる
算出型のみ定義可能

例

```swift
struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
    // return an Int value here
		return 42
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
    // return an Int value here
		return 42
    }
}
class SomeClass {
    class var computedTypeProperty: Int {
    // return an Int value here
		return 42
    }
}
```

> **NOTE**
上記の _computedTypeProperty_ は読み専用で、 _set_ や _get_  を使って r/w ができるようにもできる

#### Querying and Setting Type Properties
インスタスを定義せず、例えば、```someClass.someTypeProperty``` のように、クラス名.プロパティ名とドットで繋いでアクセスできる

```swift
println(SomeClass.computedTypeProperty)
// prints "42"
println(SomeStructure.storedTypeProperty)
// prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
println(SomeStructure.storedTypeProperty)
// prints "Another value."
```