EZ-NET 熊谷友宏 http://ez-net.jp/
2015.02.28 @ 第60回 Cocoa 勉強会関西
Swift カジュアルプログラミング
《基礎》不変値と可変値
熊谷友宏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 value = 10
// 変更はできない value = 20
▶ let で宣言された変数 ▶ 値を書き込めるのは1度だけ
Swift
可変値変数
// 値を書き込んで… var value = 10
// さらに書き換えが可能 value = 20
▶ var で宣言された変数 ▶ 何度でも書き換え可能
Swift
原則可能な限り let を使う
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 らしい安全なコードになる
目標
▶ 変数を値と状態で捉える ▶ 変数から Swift の全容を探る
目標
変数・構造体・クラスを知るとSwift はもっと楽しくなる
値とは▶ 評価したい式で使うもの ▶ 何かの式を評価したもの
用途▶ 引数 ▶ 結果
不変値
a = f(x,y,z)
不変値
▶ 引数は使う前に決まる ▶ 結果は決まったら変わらない
評価式と値
りんごは 130 円です
じゃあ、3 つください
_φ(・_・
全部で 500 円です!え? りんごっていくらだっけ
りんごは 250 円ですあれ?
そうだメモで確かめよう ほんとだ 250 円って書いてあった
???
▶ りんご = 130▶ 値段メモ.りんご = りんご
▶ 購入数 = 3▶ print 金額(りんご,購入数) 500
▶ print (りんご) 250▶ print (値段メモ.りんご) 250
不変値
変更の余地があると▶ 変更を考慮したコードを記述渡し手と受け手で意思共有も必要
▶ 取得値が勝手に変わる可能性コピーするかの判断が常に必要
煩わされる▶ そもそも変える必要性がない
値の扱いに優れた変数不変値変数 let の誕生
特徴▶ 設定したら書き変わらない ▶ 常にコピー
利点▶ 変化に備えた考慮が不要 ▶ コピーするかどうかで悩まない
不変値変数 let
三項演算子 “?:” を使いましょう
不変値変数 let
条件で値を変えたい
三項演算子による値の設定
let discountRate = (isBargainDay ? 0.03 : 0.00)
Swift
クロージャーを活用しましょう
不変値変数 let
複雑な条件で値を変えたい
クロージャーによる値の設定
let getPrice = { () -> Double? in if inStock {
return applyRate(basePrice) } else {
return nil }
}
let price = getPrice()
Swift
従来通りの即時初期化をオススメ
不変値変数 let
Swift 1.2 なら遅延初期化も可能
遅延初期化による値の設定
let price:Double?
if inStock {
price = applyRate(basePrice) } else {
price = nil }
Swift
Swift 1.2
コードを読まないと値の設定場所が分からない…
即時初期化の利点
let basePrice = 150 let discountRate
= (isBargainDay ? 0.03 : 0.00)
let price = getPrice()
Swift
▶ 傍を見れば設定値が分かる ▶ どんな場合も初期化できる、はず
状態とは▶ 時間軸で変化する値 ▶ 今の有り様を表現するもの
用途▶ プロパティ ▶ バッファー
可変値
可変値
▶ 時事刻々と変化する ▶ 状況に応じて調整可能
移動する物の位置
location: (x,y)
カップの容量
capacity: ㎖
可変値
変化する前提があると▶ 変更を常に意識できる渡し手と受け手で意思が伝わる
▶ 再取得時には変わっている可能性コピーが必要
扱い方が定まる▶ 扱いに悩む必要がなくなる
状態の扱いに優れた変数可変値変数 var の登場
特徴▶ 設定後に書き換えられる ▶ 常にコピー
利点▶ 変化を前提とした扱いが可能 ▶ コピーするかどうかで悩まない
可変値変数 var
2種類の変数
▶ コーディングの方針が定まる ▶ ソースコードの可読性が向上
宣言 内容 用途let 不変値 値var 可変値 状態
変数には用途を込められる
2種類の変数が誕生したからには言語によるサポートがある
変数の言語サポート
▶ 値と状態の相互運用 ▶ 変数に特化したオブジェクト
変数はコピーされる▶ 代入時に内容をコピー ▶ 他からの干渉を防ぐのが目的
コピー後の性質は代入先に依る▶ 可変値に不変値を入れれば変更可 ▶ 元の性質には束縛されない
値と状態の相乗りを実現変数のコピーで
この星は移動するよ!
今は (0, 0) に居るよ今はどこに居るの?
_φ(・_・横に20、縦に800、移動して!
移動したよ!
状態を可変値で宣言
今の状態を値にコピーして返却
状態の変更を不変値で指示
受け取った値を不変値にコピー
受け取った値をコピーして状態を更新
今は (20, 800) に居るよ
今はどこに居るの?
_φ(・_・
移動したよ!
前回より横に60移動したのね!
今は (80, 800) に居るよ
勝手に移動したよ!
お、今はどこに居るの?
_φ(・_・
受け取った値を不変値にコピー
受け取った値を不変値にコピー
今の状態を値にコピーして返却
今の状態を値にコピーして返却
受け取った値と以前にコピーした値を比較
なんらかの値で状態を更新
変数に特化したオブジェクト
構造体
Swift の変数は2種類
▶ 決まれば変わらない値 ▶ 時事刻々と変化する状態
Objective-C は1種類の変数で工夫
▶ Immutable クラス ▶ Mutable クラス
Immutable クラス
▶ 初期化後の状態変化を禁止 ▶ 不変値に類似
Mutable クラス
▶ 初期化後の状態変化を制限しない ▶ 可変値に類似
Objective-C ではクラス設計によって変数を制御
プログラマーの自主性に依存
Swift では言語仕様が主導権を握る
コンパイラによる変数の統制
変数の種類で制御オブジェクトの性質が格納先で変化
▶ Immutable 扱い
可変値変数▶ Mutable 扱い
変数の種類で制御
不変値変数
変数の種類で振る舞いを変える
変数の種類で制御
構造体の登場
▶ 内容を自由に設計できる ▶ 内容は別変数へ代入時にコピー ▶ 格納先に応じて振る舞いを制御
目的
構造体
値や状態を表現するオブジェクト
特徴
値や状態で使うオブジェクトは
構造体
原則、構造体で定義
▶ String ▶ Array ▶ Int
▶ 内容は可変値変数のプロパティで定義 ▶ 構造体を可変値で扱う時のみ変更可
内容の定義
構造体
struct MyValue {
var state:Int = 10 }
▶ mutating な機能のみ内容を変更可能 ▶ mutating な機能は可変値でのみ利用可 ▶ それ以外の機能は常に利用可能
機能の定義
構造体
struct MyValue {
mutating func mutableMethod(v:Int) func immutableMethod(v:Int)
}
▶ 内容は常に変更可能 ▶ デイニシャライザは存在しない
イニシャライザの定義
構造体
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 で状態を扱う
構造体▶ 値や状態に特化したオブジェクト ▶ 変数の種類で状態の不変性を制御
クラス▶ 状態の制御に特化したオブジェクト