>100 Views
February 28, 15
スライド概要
2015年2月28日の Cocoa 勉強会関西で話した、Swift における変数の2つの在り方を「値」と「状態」の観点から観察してみたお話です。
※ Docswell での公開に移行する直前の Slideshare での閲覧数は 3,453 でした。
正統派趣味人プログラマー。プログラミングとは幼馴染です。
Swift カジュアルプログラミング 《基礎》不変値と可変値 EZ-NET 熊谷友宏 http://ez-net.jp/ 2015.02.28 @ 第60回 Cocoa 勉強会関西
熊谷友宏 http://ez-net.jp/ @es̲kumagai Xcode 5 徹底解説 IP Phone 音でダイヤル 音で再配達ゴッド いつもの電卓 for iPhone いつもの電卓 for iPad 音で再配達
熊谷友宏 http://ez-net.jp/ @es̲kumagai 開催中 #yidev 横浜 iPhone 開発者勉強会
不変値と可変値 Swift にある変数のお話
Swift には 2つの変数 があります
不変値変数 ▶ let で宣言された変数 ▶ 値を書き込めるのは1度だけ Swift // 値を書き込んだら… let value = 10 // 変更はできない value = 20
可変値変数 ▶ var で宣言された変数 ▶ 何度でも書き換え可能 Swift // 値を書き込んで… var value = 10 // さらに書き換えが可能 value = 20
原則 可能な限り let を使う ➡ Swift らしい安全なコードになる Swift let prices = [100.0, 300.0, 200.0] let withTax = { $0 * 1.08 } let pricesWithTax = prices.map(withTax) let sum = pricesWithTax.reduce(0) {$0+$1}
おしまい?
今回はもう少し先のお話
目標 ▶ 変数を値と状態で捉える ▶ 変数から Swift の全容を探る
目標 変数・構造体・クラスを知ると Swift はもっと楽しくなる
不変値と可変値 役割と性質
不変値
不変値 役割 ▶ 値を表現する
不変値 値とは ▶ 評価したい式で使うもの ▶ 何かの式を評価したもの 用途 ▶ 引数 ▶ 結果
不変値 評価式と値 a = f(x,y,z) ▶ 引数は使う前に決まる ▶ 結果は決まったら変わらない
不変値 もし変わってしまったら?
りんごは 130 円です ̲φ(・̲・ じゃあ、3 つください 全部で 500 円です! え? りんごっていくらだっけ りんごは 250 円です あれ? そうだメモで確かめよう ほんとだ 250 円って書いてあった
▶ りんご = 130 ▶ 値段メモ.りんご = りんご ▶ 購入数 = 3 ▶ print 金額(りんご,購入数) 500 ▶ print (りんご) 250 ▶ print (値段メモ.りんご) 250 ???
不変値 変更の余地があると ▶ 変更を考慮したコードを記述 渡し手と受け手で意思共有も必要 ▶ 取得値が勝手に変わる可能性 コピーするかの判断が常に必要 煩わされる ▶ そもそも変える必要性がない
不変値変数 let の誕生 値の扱いに優れた変数
不変値変数 let 特徴 ▶ 設定したら書き変わらない ▶ 常にコピー 利点 ▶ 変化に備えた考慮が不要 ▶ コピーするかどうかで悩まない
不変値変数 let 使い方
不変値変数 let 条件で値を変えたい 三項演算子 “?:” を使いましょう
三項演算子による値の設定 Swift let discountRate = (isBargainDay ? 0.03 : 0.00)
不変値変数 let 複雑な条件で値を変えたい クロージャーを活用しましょう
クロージャーによる値の設定 Swift let getPrice = { () -> Double? in if inStock { return applyRate(basePrice) } else { return nil } } let price = getPrice()
不変値変数 let Swift 1.2 なら遅延初期化も可能 従来通りの即時初期化をオススメ
Swift 1.2 遅延初期化による値の設定 Swift let price:Double? if inStock { price = applyRate(basePrice) } else { price = nil } コードを読まないと値の設定場所が分からない…
即時初期化の利点 ▶ 傍を見れば設定値が分かる ▶ どんな場合も初期化できる、はず Swift let basePrice = 150 let discountRate = (isBargainDay ? 0.03 : 0.00) let price = getPrice()
可変値
可変値 役割 ▶ 状態を表現する
可変値 状態とは ▶ 時間軸で変化する値 ▶ 今の有り様を表現するもの 用途 ▶ プロパティ ▶ バッファー
可変値 移動する物の位置 カップの容量 location: (x,y) capacity: ㎖ ▶ 時事刻々と変化する ▶ 状況に応じて調整可能
可変値 変化する前提があると ▶ 変更を常に意識できる 渡し手と受け手で意思が伝わる ▶ 再取得時には変わっている可能性 コピーが必要 扱い方が定まる ▶ 扱いに悩む必要がなくなる
可変値変数 var の登場 状態の扱いに優れた変数
可変値変数 var 特徴 ▶ 設定後に書き換えられる ▶ 常にコピー 利点 ▶ 変化を前提とした扱いが可能 ▶ コピーするかどうかで悩まない
2種類の変数の誕生
2種類の変数 宣言 let var 内容 不変値 可変値 変数には用途を込められる ▶ コーディングの方針が定まる ▶ ソースコードの可読性が向上 用途 値 状態
2種類の変数が誕生したからには 言語によるサポートがある
変数の言語サポート ▶ 値と状態の相互運用 ▶ 変数に特化したオブジェクト
値と状態の相互運用 変数のコピー
変数はコピーされる ▶ 代入時に内容をコピー ▶ 他からの干渉を防ぐのが目的 コピー後の性質は代入先に依る ▶ 可変値に不変値を入れれば変更可 ▶ 元の性質には束縛されない
変数のコピーで 値と状態の相乗りを実現
相互乗り入れのイメージ
状態を可変値で宣言 この星は移動するよ! 今はどこに居るの? 今は (0, 0) に居るよ 今の状態を値にコピーして返却 受け取った値を不変値にコピー ̲φ(・̲・ 横に20、縦に800、移動して! 状態の変更を不変値で指示 受け取った値をコピーして状態を更新 移動したよ!
移動したよ! 今の状態を値にコピーして返却 今はどこに居るの? 今は (20, 800) に居るよ ̲φ(・̲・ なんらかの値で状態を更新 勝手に移動したよ! 受け取った値を不変値にコピー お、今はどこに居るの? 今は (80, 800) に居るよ 今の状態を値にコピーして返却 受け取った値を不変値にコピー ̲φ(・̲・ 受け取った値と以前にコピーした値を比較 前回より横に60移動したのね!
変数に特化したオブジェクト 構造体
おさらい
Swift の変数は2種類 ▶ 決まれば変わらない値 ▶ 時事刻々と変化する状態 Objective-C は1種類の変数で工夫 ▶ Immutable クラス ▶ Mutable クラス
Immutable クラス ▶ 初期化後の状態変化を禁止 ▶ 不変値に類似 Mutable クラス ▶ 初期化後の状態変化を制限しない ▶ 可変値に類似
Objective-C では クラス設計によって変数を制御 プログラマーの自主性に依存
Swift では 言語仕様が主導権を握る コンパイラによる変数の統制
変数の種類で制御 オブジェクトの性質が格納先で変化
変数の種類で制御 不変値変数 ▶ Immutable 扱い 可変値変数 ▶ Mutable 扱い
変数の種類で制御 変数の種類で振る舞いを変える 構造体の登場
構造体 目的 値や状態を表現するオブジェクト 特徴 ▶ 内容を自由に設計できる ▶ 内容は別変数へ代入時にコピー ▶ 格納先に応じて振る舞いを制御
構造体 値や状態で使うオブジェクトは 原則、構造体で定義 ▶ String ▶ Array ▶ Int
構造体 定義方法
構造体 内容の定義 struct MyValue { var state:Int = 10 } ▶ 内容は可変値変数のプロパティで定義 ▶ 構造体を可変値で扱う時のみ変更可
構造体 機能の定義 struct MyValue { mutating func mutableMethod(v:Int) func immutableMethod(v:Int) } ▶ mutating な機能のみ内容を変更可能 ▶ mutating な機能は可変値でのみ利用可 ▶ それ以外の機能は常に利用可能
構造体 イニシャライザの定義 struct MyValue { init() } ▶ 内容は常に変更可能 ▶ デイニシャライザは存在しない
構造体 まとめ ▶ 値や状態に特化したオブジェクト ▶ Immutable な振る舞いが基本 ▶ Mutable な機能は明示定義 状態変化を伴う機能か見て分かる ▶ 使用中でも不変性を振替可能 コピーするので元の値に干渉しない
構造体 オブジェクト設計における プログラマーへの負担が激減
クラスは?
クラス 目的 状態を制御するオブジェクト 特徴 ▶ 状態を制御する機能の集合体 ▶ 内部に状態を持つ
クラス UI の制御など 制御機能の設計時に使用
クラス 状態は共有する ▶ 制御する状態は共有 ▶ 代入時は実体がコピーされる 状態はコピーされない ▶ 不変値変数は実体の不変性を保証 状態の不変性は保証しない
クラス 状態 制御 制御 複製 実体 実体
クラス 性質を踏まえた扱い方 状態もコピーしたい ▶ 同じ状態の新しい実体を作成 状態の不変性を保証したい ▶ Immutable クラスを自身で設計 不変値のときに Immutable にしたい ▶ コンセプト的に無理
クラス そもそもクラス? ▶ 実体をコピーするときに 状態もコピーする必要性が生じた ▶ 状態の不変性を保証が必要になった そんなときは 構造体での実装も検討する
クラス 定義方法
クラス 状態の定義 class MyValue { var state:Int = 10 } ▶ 状態は可変値変数のプロパティで定義 ▶ 実体を不変値で扱う時でも変更可
クラス 機能の定義 class MyValue { func method(v:Int) } ▶ 機能内から状態を変更可能 ▶ 変数の種類を問わず利用可能
クラス イニシャライザの定義 class MyValue { init() deinit } ▶ 状態は常に変更可能 ▶ デイニシャライザでの後始末が可能
クラス まとめ ▶ 機能に特化したオブジェクト ▶ 状態を共有して制御する 実体を複製して共通の状態を制御可能 ▶ 不変性が保証するのは実体だけ 状態操作できないクラスは無価値
総括
総括 変数・構造体・クラスを知ると Swift はもっと楽しくなる
総括 2種類の変数 ▶ 不変値変数 let で値を扱う ▶ 可変値変数 var で状態を扱う 構造体 ▶ 値や状態に特化したオブジェクト ▶ 変数の種類で状態の不変性を制御 クラス ▶ 状態の制御に特化したオブジェクト