型・型推論
Swiftでは値を代入する際に、静的な型推論を行っています。そのため、型宣言を明示的に記述することなく、自動的に型を決定できます。次のコードを見てください。
var num = 10 num = "This is String" // コンパイルエラー
型推論とは、プログラミング言語で用いる変数や関数の型をリテラルやその他コンテキストの情報によって自動的に決定する機構のことです。Objective-Cのような明示的な型の宣言は、Swiftでは必須でなくなりました。
ここでは「num」が、宣言時に整数型として推論されます。もちろん、明示的に型を宣言することも可能です。
また、次のコードでは、他の多くの言語やObjective-Cで行われていたようなプリミティブな型同士の暗黙的な型変換が行われていないことが見て取れます。
var degree: Double = 10 let integer: Int = 12 degree = integer // コンパイルエラー let char = "a" as Character var str = "string" str = char // コンパイルエラー
ただし、「+」などでリテラルから計算するときには、計算結果から型推論していることに注意してください。
let pi = 3 + 0.14 // pi: Double
明示的な型変換のためには、次のコードの2行目のように、各値型のイニシャライザでくるむ必要があります。
var newdegree = degree + integer // コンパイルエラー let newdegree = degree + Double(integer)
また、次回以降紹介するクロージャなども、強力な型推論のしくみを備えています。
タプル
Objective-Cにはなかった新しい混合値としてタプルが扱えるようになりました。タプルでは複数の型を持った値でもひとつのまとまった値として扱えるようになります。
let john = ("jun john sakurai", 1933)
タプルから構成要素にアクセスする場合には、タプル内変数とともにタプル値を宣言し、代入する方法があります。
let (fullname, birth) = john // fullname = "jun john sakurai", birth = 1933
また、タプルの要素には、左端を0番として数えた番号でアクセスすることも可能です。
let johnName = john.0 let johnBirth = john.1
次のように、タプルの各要素に名前をつけて宣言することもできます。
let freddie = (fullname: "freddie mercury", birth: 1946)
この場合は「.要素名」で各要素にアクセスすることが可能です。
let fredName = freddie.fullname // fredName = "freddie mercury" var fredBirth = freddie.birth // fredBirth = 1046
もちろん、タプルでも型推論は効いています。
birth = fullname // コンパイルエラー birth: Int型 fullname: String型
コレクション型
Swiftでは、Objective-CのNSArrayクラスに対応するArray、NSDictionaryクラスに対応するDictionaryを、共にコレクション型として扱えます。
var animals = ["dog", "cat", "elephant"] // Array<String> var countries = ["JPN" : "Japan", "USA" : "America"] // Dictionary<String, String>
また、コレクション型にも型推論が適用されます。このコードの場合、「animals」はArray<String>型として型推論され、「countries」はDictionary<String, String>型として型推論されています。
<>付きの型はジェネリクスと呼ばれ、型を指定するためのJavaなどで使われている記法です。次回以降に解説の予定です。現段階では、付随する型情報を追加するための記法だと思って読み進めてください。
Objective-Cのコレクションクラスでは型情報が抜け落ちてしまうため、同じ型を持つコレクションを扱うときにも、キャストなどを用いて型情報を決定する場面が多々ありました。型情報を決定しないと、ドット記法によるメソッド呼び出しができません。
NSArray *animals = @["dog", @"cat", @"elephant"]; NSString *dog = animals[0]; // .記法でNSStringのメソッドを直接呼び出せないため、いったん型情報を決定する。 dog.upperCaseString;
Swiftの場合、宣言時にコレクションの型が決められるため、型を指定するためのコードを書く必要がほぼなくなります。
animals[0].uppercaseString // "DOG"
さらに、SwiftではArrayの要素を取り出す方法が単純になりました。
// 要素取得 animals[1] // "cat" animals[0...1] // ["dog","cat"] を取得
また、可変なArrayは要素の値を自由に操作できます。
// 要素追加
animals.append("lion") // 単一要素の追加
animals += ["human", "chimpanzee"] // 複数要素の追加
animals.insert("lama", atIndex: 4) // 単一要素の挿入
// 要素更新
animals[0] = "wolf" // 0番目の要素を更新
animals[5...6] = ["coara", "kangaroo"] // 5,6番目の要素を更新
// 要素削除
let removedAnimal = animals.removeAtIndex(0) // removedAnimal = "wolf"
animals = [] // animalsの要素をすべて削除
Dictionaryに関しても、同じような処理で要素の追加・取得・更新・削除ができます。
// 要素追加
countries["CHA"] = "China"
// 要素取得
countries["JPN"]
// 要素更新
let oldValue = countries.updateValue("United States Of America", forKey: "USA") // oldValueに更新前の値がオプショナル列挙型にくるまれて渡される
countries["USA"] = "United States Of America"
// 要素削除
let removedValue = countries.removeValueForKey("JPN") // removedValueに削除前の値がオプショナル列挙型にくるまれて渡される
countries["CHA"] = nil
Objective-Cとは異なり、Swiftではnilの可能性を持った値については、コンパイル時により検知しやすいように新しい型としてオプショナル列挙型として定義されています。詳細については、次回以降に解説する予定です。
