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

  • 53
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

The Swift Programming Language をまとめるトップ

Properties(プロパティ)

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

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

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

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

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

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

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

Stored Properties(保持型プロパティ)

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

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

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 を定数で宣言すると変数で宣言してあるプロパティも変更できなくなる

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

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

Lazy Stored Properties(動的に生成される保持型プロパティ)

@lazy

_@lazy_ をプロパティンの前に付けると、そのプロパティにアクセスされた時にプロパティへの定義が実際に呼ばれる

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

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 を使ってその他のプロパティの値をセットしたり取得したりする
値が確定していないので、算出プロパティは必ず変数として宣言する

以下の様に書ける

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 が自動でセットされる
以下が簡略書式

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 だけ書いて簡略化できる

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 を使ってアクセスできる

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 に近い

setget 算出型も定義できる

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

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

Type Property Syntax(タイププロパティシンタックス)

タイププロパティはその型の中にある

static

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

class

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

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 は読み専用で、 setget を使って r/w ができるようにもできる

Querying and Setting Type Properties

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

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