開発メモ

開発関係のメモをいろいろと。たぶん。

The Swift Programming Languageのメモ(その2)

はじめに

これは、『The Swift Programming Language』を読んだ時の個人的なメモです。なので、引用はすべて『The Swift Programming Language』から。

iTunes - ブック - Apple Inc.「The Swift Programming Language」
https://itunes.apple.com/jp/book/swift-programming-language/id881256329?mt=11

その1はこちら。

The Swift Programming Languageのメモ(その1) - 開発メモ
http://seeku.hateblo.jp/entry/2014/06/05/182519


Functions and Closures

  • 『func』で関数を宣言できるよ
  • 戻り値の型は『->』に続けて書くよ
func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
  • 戻り値にはタプルも使えるよ
func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
getGasPrices()
  • 決まってない数の引数は、配列として渡されるよ
  • 関数はネストできるよ
    関数の中の関数は、外の変数にアクセスできるよ。
  • 関数を戻り値や引数にすることも出来るよ

  • 実は、関数はクロージャの特別な使い方なんだよ

  • クロージャは無名で使えるよ
    この場合、inで引数と本文を区切るよ。
numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
    })
  • クロージャを簡潔に書くために、いろんな方法があるよ
  • はっきりしてる場合なら、引数や戻り値の型を省略できるよ
  • 1文だけのクロージャなら、暗黙の内に値が返されるよ
numbers.map({ number in 3 * number })
  • 引数を数字で参照することも出来るよ
sort([1, 5, 3, 12, 2]) { $0 > $1 }

Objects and Classes

  • 『class』でクラスを定義できるよ
  • 変数も定数もメソッドも、同じように書くよ
class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

メモ: クラス関係は、ほとんどがよくある形

  • 初期化する時は『init』メソッドが使われるよ
  • インスタンスを生成するときは、すべてのプロパティを割り当てる必要があるよ
  • 破棄する時は『deinit』メソッドが呼び出されるよ
    メモ: この命名はどうなの?

  • 共通のスーパークラスなんてないよ!

  • サブクラスで元のクラスのメソッドをオーバーライドする時は『override』を付けるよ
    『override』無しでオーバーライドするとコンパイル時にエラーになるよ。

  • getterやsetterも作れるよ
    メモ: この辺の実装はC#っぽい

  • setterだと、新しい値を『newValue』で参照できるよ
    メモ: この命名はどうなの?

  • プロパティが変更される前/変更された後に処理を行うことも出来るよ
    『willSet』と『didSet』を使うよ。
    メモ: この機能って本当に必要?

  • クラスのメソッドと通常の関数は1つ大きな違いがあるよ

  • 関数の場合、引数名はどれも関数の中だけで使われるよ
  • メソッドの場合、引数名がメソッドを呼び出すときにも使われるよ
    引数名が必要なのは、2個目以降の引数だけだよ。
    引数名に、メソッドの中だけで使われる別名をつけることも出来るよ。
    メモ: いまさら、引数名って必要? 本当に必要なの?
class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
  • オプション変数を使うとき、『?』を一緒に使えるよ
  • 『?』の前のオプション変数がnilだった場合、式全体がnilになるよ
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

Enumerations and Structures

  • enum』で列挙型を定義できるよ
  • クラスと同じように、メソッドを持たせることも出来るよ
  • 元になる型(=raw value)は文字列型や浮動小数点型も使えるよ
  • 『toRaw』や『fromRaw』で、元になる型と変換できるよ

  • 『struct』で構造体を定義できるよ

  • 構造体はクラスとほとんど同じだよ
  • 構造体は値渡しでクラスは参照渡しになるよ

  • 列挙型のインスタンスは値を持つことが出来るよ
    メンバーごとに別々の値を持つことが出来るよ。
    値の型は、元になる型と関係ないよ。

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}
 
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")
 
switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure...  \(error)"
}

Protocols and Extensions

  • 『protocol』でプロトコルを定義できるよ
  • クラスも列挙型も構造体も、プロトコルを使えるよ
  • メソッドに『mutating』をつけると、構造体のプロパティを変更できるよ
    クラスのプロパティはいつでも変更できるよ。
    メモ: デフォルトでは、構造体と列挙型のプロパティはインスタンスメソッドから変更できない

  • 『extension』で既存の型にメソッドを追加できるよ

  • プロトコルは他の型と同じように使えるよ

Generics

func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {
    var result = ItemType[]()
    for i in 0..times {
        result += item
    }
    return result
}
repeat("knock", 4)
  • 関数やメソッドやクラスや列挙型や構造体で、ジェネリックが使えるよ
  • 『<>』の中で引数の後に『where』で続けて、必要な要素を指定できるよ
    メモ: この辺の実装はC++のテンプレートっぽい

とりあえずここまで。 (2014/06/06)