この記事はSwift発表当初に書いたものです。最新のSwiftの仕様に則っていない箇所もあるのでご留意ください。
The Swift Programming Language を読みながら適当に。
間違いや勘違いはあとから修正していくスタイル。(最後の方は本当に適当)
-
基本
- LLVMにコンパイルされる
- なのでObjective-CやC/C++とも(ある意味)互換性がある
- Objective-Cとも混在できる(専用のヘッダファイルが必要)
-
基本構文
- どうやら末尾の;は必要ないらしい
-
変数
- letで定数宣言(constに似たイメージ、再代入禁止という方が妥当な表現かも)
- varで変数宣言(普通に宣言したみたいな)
-
型
- 型は明示しなくてもいい
let foo = 10
- 明示する場合は後ろに書く
let foo: Double = 10
- 暗黙の型変換は行われない
- 型は明示しなくてもいい
-
文字列
-
@""ではなく""で宣言できるようになった
-
文字列に変数を埋め込む場合は()構文がある
let old = 17 let foo = "I am \(old) old years."
-
-
配列、Dictionary
-
Array
var array = ["apple", "orange", "banana"]
-
Dictionary
var names = [ "Yamada": "Taro", "Tanaka": "Jirou", ]
-
ジェネリクスで型指定
// だいたいJavaと同じ let emptyArray = String[]() let emptyDictionary = Dictionary<String, Float>()
-
-
制御構文
- for-in
for player in players { }
- if-else
if old < 20 { } else { } // 条件式全体を()で囲む必要がない!
-
Optional
- 変数宣言に?を付けることでnilが代入できるようになる。
- Option[T]のシンタックスシュガー(らしい、今度調べる)
var optionalString: String? = "Hello" if let foo = optionalString { // ここではfooがnilでないことが保証される? } // ScalaのOption型と似た考え方。
-
switch
- 変数にバインドして判定も可能
let filename = "foo.txt" switch filename { case: "bar.txt": // 明示的なbreakは不要 case: let f where f.hasSuffix(".txt") // let where による条件判定 default: // default }
-
key-value pair(タプル)
- Dictionaryをfor-inで走査するときにkeyとvalueのタプルに分解できる
// 型を明示しないで良い for (name, phoneNumbers) in addresses { }
-
while, do-while
- 普通なので省略
-
Range(n..m)
-
n..m
でRange(範囲)を表すことが出来る
for i in 0..3 { }
-
-
関数
- とりあえず基本形
// 変数:型 で引数指定 // -> で関数の戻り値の型を指定 // (だいたいScalaの構文をそのまま持ち込んでる印象) func greet(firstName: String, lastName: String) -> String { return "My name is \(firstName) \(lastName)." } greet("Yamada", "Taro")
- 複数の値を関数で返せる
func foo() -> (Int, Int, Int) { } // Scalaと違って配列で返すので数の制限は無し?
-
可変長引数
for sum(numbers: Int...) -> Int { }
-
関数はネストできる
func foo() { func bar() { } bar() }
-
関数はファーストクラス(引数や戻り値にそのまま使える)
// conditionに「Intを引数にBoolを返す関数」を受け取る func numberFilter(numbers: Int[], condition: Int -> Bool) -> Int[] { } // 「Int型を引数に取り、Int型を返す関数」を返す関数 func foo() -> (Int -> Int) { }
-
map関数サポートしてるよ!
// 数値配列numbersの値を全て2倍にする numbers.map({ (number: Int) -> Int in let result = number * 2 return result }) // 省略するとここまで短く書ける numbers.map({ number in number * 2 }) // ちなみにこんなことも(シンタックスシュガーでしょうが) sort([1, 5, 3, 12, 2]) { $0 > $1 }
-
クラス、オブジェクト
-
クラス宣言
class Person { // インスタンス変数 // 全てのインスタンス変数は宣言またはinitで初期化する必要がある var name: String var age: Int = 0 // コンストラクタ init(name: String) { self.name = name } // メソッド func greet() -> String { } // deinitを宣言するとデストラクタとして機能する }
-
インスタンス化
var person = Person() // newキーワードなし(ScalaのTypeClassみたい)
-
オーバーライド(override)
-
override
キーワードをつけないとコンパイルエラー
override func foo() -> String { }
-
-
継承(: SuperClass)
// :のあとに親クラス名(だいたい最近のモダン言語と同じシンタックス) class Person: Animal { }
-
プロパティ(get/set)
var foo: Int { get { return bar * 2 // 意味のあるコードではありません } set { foo = newValue / 2 // setの値は`newValue`に格納される }
-
プロパティの監視(willSet/didSet)
// 値の取得・設定をカスタマイズしたくはないけど監視だけしたい場合は以下のようにする // CocoaTouchで採用されているKVOを実現するための機構? var foo: Int { willSet { } }
-
メソッド
// 宣言 class Person { // 第2引数はシグネチャとしては`lastName`、内部変数としては`ln`が採用される // (これにより無駄にコードが長くなることがなくなりそう) func greet(firstName: String, lastName ln: String) -> String { return "My name is \(firstName) \(ln)."¥ } } // 呼び出し ver yamada = Person() yamada.greet("Yamada", lastName: "Taro") // この辺りはObjective-Cゆずり
-
-
列挙型(enum)
-
メソッドも定義できるよ!(実装的にはSingleton限定のクラスともみなせる)
-
バイナリ(数値とか)からenumへの変換
fromRaw
とか、その逆toRaw
もできるよ! -
列挙値は複数の引数を持つことも出来る!
// このあたりHaskellのLeft|Rightを思い出す enum Result { case Success(String, String) case Error(String) }
-
-
構造体(struct)
- 殆どクラスと一緒だよ!
- 最大の違いはクラスの場合は参照渡しだけど、構造体はコピー渡しってことだよ!
-
プロトコル(protocol)
-
クラス、列挙型、構造体、どれもがプロトコルを採用できる。
-
宣言
protocol ExampleProtocol { var foo: String { get } // 必須のreadプロパティ mutating func bar() // ミュータブルな操作としてのマーク?(よく分からん) }
-
採用
// 継承と一緒(継承と一緒にやりたい場合どうするんだろ?) class Person: ExampleProtocol { }
-
-
拡張(extension)
-
カテゴリ拡張みたいに既存のクラスも拡張できちゃうよ。
// 旧カテゴリ拡張だけどもScalaを彷彿とさせる・・・ // (以下だいたい本からの丸写し) extension Int: ExampleProtocol { var simpleDescription: String { return "I am a number of \(self)." } mutating func adjust() { self += 42 } } 7.simpleDescription
-
-
ジェネリクス(Generics)
-
ようやくジェネリクスが使えるよ(やったね!)
// あえてJava風にTとか書いてみる func repeat<T>(item: T, times: Int) -> T[] { }
-
switchと同じく条件を絞ったり出来るよ(コード割愛)
-