Subscripts
昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/Subscripts.html を読む。
- クラス、構造体、列挙型は
subscript
を定義できる subscript(index: Int) -> String { get{ return …} set(newValue){〜} }
set
のデフォルトパラメータ名はnewValue
subscript(index: Int) -> String { return …}
読み取り専用- 配列[index] 辞書[key] のようにアクセスできる
- 一つの型に複数
subscript
を定義できる(オーバーロード) - 添字形式
[]
を使っている文脈で型推論されて適切なやつが選ばれる- 曖昧なときはコンパイルエラー
- 入力パラメータの数はいくつでも。パラメータの型は何でも
- 返り値の型はなんでも
- パラメータは可変引数にできる
inout
パラメータは使えない。デフォルトパラメータ値はできない
Methods
昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/Methods.html を読む。
- 構造体と列挙型にメソッドを定義できることがCやObjective-Cとの大きな違い
- どの型のインスタンスにも
self
と呼ばれる暗黙のプロパティがある - 構造体と列挙型では
mutating
キーワードをfunc
の前に書いてオプトインする - 構造体と列挙型では
mutating
なインスタンスメソッドはlet
したインスタンスでは呼べない mutating
なインスタンスメソッドでself
書き換えself = Point(x: x + deltaX, y: y + deltaY)
- 型メソッドは要するにObjective-Cでのクラスメソッドのこと
- 型メソッドでの
self
は型そのものを参照する - 返り値を無視しても間違いじゃないメソッドには
@discardableResult
属性
self
はプロパティやったんや…
this
ポインタのキーワードが違うだけやなかった…
という初めて知る事実に驚愕
Properties
age++ //=> Unary operator '++' cannot be applied to an operand of type '@lvalue Int'
昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/Properties.html を読む。
struct
のインスタンスがlet
ならプロパティがvar
でも値変更できない=>コンパイルエラー- クラスのインスタンスが
let
でもプロパティがvar
なら値を変更できる - 遅延プロパティは
lazy
修飾子を宣言の前につけるlazy
ならvar
である。let
はlazy
にできない- 遅延プロパティが有益なのは
- 初期値が外部要因に依存しててインスタンスの初期化時に決まらない時
- 初期値を決めるのに複雑計算量が多い時
- 遅延プロパティにマルチスレッドで同時にアクセスしたとき一度しか初期化されないという保証はない
- プロパティ値をインスタンス変数に保持しておく Objective-C みたいなやりかたはやらない
- 計算型プロパティのsetterのパラメータ名指定は
set(パラメータ名)
デフォルトのパラメータ名はnewValue
- 読み取り専用の計算型プロパティであっても宣言は
var
- オブザーバーとは
willSet
とdidSet
- 新しい値がプロパティの現在の値と同じであっても、プロパティの値が設定されるたびに呼び出される
- 定義できるのは
lazy
プロパティ以外 - サブクラスでオーバーライドできる
willSet
のデフォルトパラメータ名はnewValue
didSet
のデフォルトパラメータ名はoldValue
- superクラスの初期化が終わった後、subクラスの初期化中、superクラスのプロパティのオブザーバーは呼び出される
- クラス自身のプロパティ設定中、superクラスの初期化が呼ばれる前は、呼び出されない
inout
宣言されたfunc
の引数にプロパティを渡すとオブザーバーがいつも呼び出される
- グローバル定数・変数がつかえる…のを今知った
- いつも遅延評価される。
lazy
修飾子をつける必要は無い。つけたらコンパイルエラー - ローカル定数変数は決して遅延評価されない
- 計算型にできる、オブザーバーを定義できる
- いつも遅延評価される。
- 型プロパティは要するに
static
のこと- 初期化子が無いのでデフォルト値が必要
- マルチスレッドで同時にアクセスしても一度だけしか初期化されないことが保証されている
static
ではなくclass
キーワードを使うとサブクラスでオーバーライドできる
Classes and Structures
光速に近づくと時間がゆっくり進むらしい。 つまり飛行機や新幹線の中で仕事をすると時間に余裕が生まれる。
昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html を読む。
- 一般的なガイドラインとして、構造体や列挙型が好ましい。クラスは適切か必要なときに使うがよい
- 実際にはカスタムデータ型のほとんどが構造体や列挙型
- 型名(クラス名、構造体名、列挙型名)には、UppserCamelCase
- プロパティ名とメソッド名には、lowerCamelCase
- プロパティにアクセスする dot syntax は空白なし
- memberwise initializer があるのは構造体だけ
- 構造体と列挙型は値型
- クラスは参照型
- 同一演算子
===
!==
が使えるのはクラスのインスタンスだけ
なんだか「ふつうstruct
かenum
だよね」みたいなことをいわれたけど
気にしないでclass
を使っていくスタイル。
Enumerations
enum 吉凶 { case 大吉, 吉, 中吉, 小吉, 末吉, 凶 }
前回に続いて https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html を読んでいる。
メモ
- 列挙型の名前には複数形より単数形を与えよ
- 型推論できるときは簡略形で書ける
let x: Planet = .mercury
CaseIterable
はSwift4.2から- 関連付けられた値を
switch
〜case
構文の中で取り出すcase .upc(let numberSystem, let manufacturer, let product, let check):
let
をまとめて外に出せるcase let .upc(numberSystem, manufacturer, product, check):
- 暗黙の raw values にできるのは整数か文字列だけ
- enumの再帰 関連付けられた値に自分自身のEnum型を使う場合
indirect
enum は A Swift Tour でもう充分に驚いたので ここではそんなに驚きは少なかった。
Closures
lambda を「らんびだ」と呼んでいた人を思い出す。
前回に引き続いて https://docs.swift.org/swift-book/LanguageGuide/Closures.html を読んでいる。
気になった事
- グローバル関数とネストされた関数はクロージャの特別なやつ
- 一般的な形式
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
- 型推論できる型は省略できる
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
- クロージャの本体が式一個のときは
return
を省略できるreversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
- 引数リストを簡略表記にして
in
も省略できるreversedNames = names.sorted(by: { $0 > $1 } )
- 演算子メソッドを使う場合
reversedNames = names.sorted(by: >)
- 関数の最後のパラメータにクロージャを渡す場合は括弧
()
の外側にぶら下げられるreversedNames = names.sorted() { $0 > $1 }
- クロージャが唯一のパラメータなら括弧
()
も省略できるreversedNames = names.sorted { $0 > $1 }
- 値のキャプチャーは他のプログラム言語のラムダ式なんかと同じ
- 渡したクロージャが何処かに登録されて後で使われるような場合
@escaping
を「パラメータ名:」と「型名」の間に書くfunc addEventListener(l: @escaping () -> Void) {〜}
この場合@escaping
を付けないとコンパイルエラー - 関数に式を渡すとき自動的にクロージャにしてくれる
@autoclosure
を「パラメータ名:」と「型名」の間に書くfunc log(_ message: @autoclosure () -> String) {〜}
@autoclosure
は遅延評価に便利@autoclosure
の使いすぎに注意。 訳わからんようなるので
いままで読んだ中でクロージャのところがいちばん面白かった。
Functions
土日のほうがやることが多いのはなぜか
前回に引き続いて https://docs.swift.org/swift-book/LanguageGuide/Functions.html を読んでいる。
気になった事
Void
型の関数は空のタプルを返す- 関数が返した値を使わない時
_ = f()
- タプルのオプショナル型
(Int, Int)?
- argument label と parameter name
- argument label の省略
_
- デフォルト値
func f(a: Int, b: Int = 123)
- 可変パラメータ
func f(_ numbers: Double...) -> Double {
中身は配列 - 変数渡し
func swap(_ a: inout Int, _ b: inout Int) {
swap(&x, &y)
デフォルト値や可変パラメータにはできない - 関数型の変数
var f: (Int, Int) -> Int = g
- 関数型のパラメータ
func g(_ f: (Int, Int) -> Int) {
- 関数型の帰り値
func f() -> (Int) -> Int {
- 関数のネスト