PR

Swiftの変数の宣言とデータ型について

2018年2月1日(木)
大津 真
Swiftの変数の宣言とデータ型を、Objective-Cと比較しながら解説します。

はじめに

今回は、Swiftにおける変数の宣言方法と、標準で用意されているデータ型の概要を駆け足で見ていくことにしましょう。前回、前々回で紹介したPlaygroundを使用して実際にコードを入力して確認しながら読み進めても良いでしょう。

変数の宣言について

Swiftでは変数の宣言を、varキーワードを使用して行います。

var 変数名:型

例えばInt型の変数ageを宣言して、値に「44」を代入するには次のようにします。

リスト1:変数の宣言と代入

var age:Int
age = 44

次のように1行で記述しても構いません。

リスト2:宣言と代入は同時に行える

var age:Int = 44

型の推論機能

上記の例では、Objective-Cにおける変数宣言と同じように、型を明示していました。これを「型アノテーション」と呼びます。Swiftでは、宣言と同時に値を代入する場合、型アノテーションなしに型を判定してくれる「型推論機能」が用意されています。次に例を示します。

リスト3:型推論の例

var age = 44    // Int型
var name = "山田太郎"     // String型
var rate = 104.5 // Double型

上記のように、代入する値が整数の場合にはInt型、文字列はString型、浮動小数点数の場合にはDouble型と判断されます。なお、カンマ「,」で区切ることにより、複数の変数を1行で宣言できます。

リスト4:カンマ「,」用いて複数の変数をまとめて宣言する

var year = 2018, pref = "東京都", weight = 55.5 // <-Int型、String型、Double型
型名を調べるには

Swift 3以降では、値の型名を取得するためにtype(of:)関数を使用します(Swift 2以前に型名を取得するのに使用されていたdynamicTypeプロパティは廃止されました)。

リスト5:type(of:)関数の使用例

var age = 44
print(type(of: age)) // -> Int

定数として宣言する

varキーワードの代わりにletキーワードで宣言した場合は定数扱いとなり、後から値を変更できなくなります。

リスト6:定数の宣言にはletを用いる

let birthYear = 1985 // letで定数として宣言
birthYear = 1986  // <-エラー

整数型について

整数の値を管理するデータ型の代表がInt型です。変数を宣言して値を代入すると、型推論によりInt型となります。それ以外にもデータ長に応じて、「符号付整数型」と「符号なし整数型」が各4種類、合計8種類の整数型が用意されています。

整数型

符号付き整数型符号無し整数型データ長
IntUInt32ビット環境では32ビット、64ビット環境では64ビット
Int8UInt88ビット
Int16UInt1616ビット
Int32UInt3232ビット
Int64UInt6464ビット

IntおよびUIntは、32ビット環境と64ビット環境でビット長が異なります。ただし、XcodeのSwiftで作成可能なMacアプリは、64ビット版のみです。また、iOS11以降は32ビットアプリは完全に対象外となったため、現在ではInt = Int64、UInt = UInt64と考えて良いでしょう。

なお、Int型以外の整数型を使用するには、型アノテーションが必要です。例えばInt8型の変数pointを宣言して、値に「95」を代入するには次のようにします。

リスト7:Int型以外の整数型は型アノテーションが必要

var point:Int8 = 95

また、これらの型は全て構造体(struct)として定義されています。例えば、Int8型はInt8構造体として定義され、maxプロパティで最大値、minプロパティで最小値を表示できます。

リスト8:Int8構造体

print(Int8.max) // -> 127
print(Int8.min) // -> -128

浮動小数点型について

浮動小数点型は、小数点以下の値を持つ数値(実数)を表すための型です。SwiftではDouble型とFloat型の2種類の構造体が用意されています。

浮動小数点型

データ長
Float32ビット
Double64ビット

型アノテーションなしで宣言するとDouble型になります。

リスト9:型アノテーションなしで実数を代入するとDouble型に

var num1 = 3.14 // Double型

Float型の変数を宣言するには、明示的に型を指定する必要があります。

リスト10:Float型の宣言

var height:Float = 174.5 // Float型
データ長を調べるには

Swift 3以降では、型のデータ長を調べるには「MemoryLayout<T>.size」を使用します(Swift 2以前に用意されていたsizeof()関数は廃止されました)。

リスト11:型のデータ長を調べる

print(MemoryLayout<Int>.size) // -> 8
print(MemoryLayout<Float>.size) // -> 4
print(MemoryLayout<Double>.size) // -> 4

Swiftは型に厳格

Swiftは型に厳格な言語です。例えばObjective-Cの場合、次のようにint型の値をdouble型の変数に代入できました。

リスト12:Objective-Cの例

int a = 5;
double b;
b = a;

上記の例のように、代入によって値の精度が変わらないケースでも、Swiftではエラーになります。

リスト13:Swiftではエラーとなる

var a:Int = 5
var b:Double;
b = a //  <- エラー

Int型の値をDouble型の変数に入れたい場合は、次のようにDouble型のイニシャライザを使用して、Int型をDouble型に変換してから代入する必要があります。

リスト14:明示的に変換してから代入

b = Double(a)

前述の例では整数と浮動小数点数の間での変換でしたが、Int8型とInt型といったように、同じ整数型同士でも、型が異なる場合には変換が必要になります。

リスト15:整数型間でも変換が必要

var num1:Int8 = 34
var num2:Int = Int(num1)  + 1 // Int8型をInt型に変換

文字列はString型

Swift標準の文字列は、String構造体のインスタンスです。Objective-Cと同様に、文字列リテラルはダブルクォートで囲みます。次にString型の変数strを宣言して、"こんにちは"を代入する例を示します。

リスト16:String型の宣言と代入

var str:String = "こんにちは"

型アノテーションを省略した場合には、自動的にString型と見なされます。

リスト17:文字列リテラルの代入でString型と見なされる

var str = "こんにちは"

また、Objective-Cでは文字列の連結にはstringWithFormat:メソッドを使用していましたが、Swiftでは+演算子で簡単に連結できます。

リスト18:文字列の連結は+演算子

var yourName = "山田" + "花子"  // "山田"と"花子"を連結

NSStringのクラスの利用

Swiftでも、Objective-Cで使用されていたFoundationフレームワークのNSStringクラスを使用することが可能です。

リスト19:NSstringクラスを利用できる

var name:NSString = "田中一郎"

NSString型とString型は相互変換可能です。NSString型の文字列を、String型にキャストするには次のように「変数名 as String」を使用します。

リスト20:NSstring型をString型にキャスト

var str:String = name as String

文字数を正しくカウントできる

Swiftの文字列に特徴的なのは、いくつかのビュー(view)という概念で文字列を操作できるようになっている点です。例えば、CharacterViewでは文字列を画面での見た目の文字として、UTF16Viewでは文字エンコーディングUTF-16のバイト列データとして扱うことが可能です。ここで言う「見た目の文字」とは、エディタでのカーソルの移動単位と考えてください。

String型の詳細についてはまた別の機会に解説するので、ここではCharacterViewを使用すると、文字列を見た目の文字そのものとして扱えると覚えておいてください。

例えば、Swift 3までは文字列の長さを求めるには、charactersプロパティでCharacterViewを取得し、そのcountプロパティを使用していました。

リスト21:文字列の長さを求める(Swift 3まで)

var str:String = "こんにちは"
print(str.characters.count) // -> 5

Swift 4では、String型のcountプロパティで文字列の長さを取得することができるようになりました。

リスト22:文字列の長さを求める(Swift 4)

print(str.count)  // -> 5

これは、Objective-Cで標準であったNSString型のlenghtプロパティを使用した結果と同じです。

リスト23:NSString型のlengthプロパティ

var nsStr:NSString = "こんにちは"
print(nsStr.length) // -> 5

NSStringとStringの大きな相違が、「1文字」の取り扱いです。例えば、前者はUTF-16のバイト列で文字を管理し、lengthプロパティはその長さを戻すため、必ずしも見た目の文字数とは限りません。それに対してcountプロパティはきちんと文字数を戻します。

例を示しましょう、Unicodeでは「だ」という文字は、「だ」(U+3060)の他に「た」(U+305f)+ 濁点(U+3099)の組み合わせでも表現できます。NSString型では後者の表現を2文字と認識しますが、String型の場合は正しく1文字となります。次に、「たかだ」という文字列の長さを求める例を示します。

リスト24:「たかだ」の長さは?

var str = "たかた" + "\u{3099}" // たかだ
print((str as NSString).length) // -> NSString型では4文字
print(str.count)  // -> String型では3文字

またUnicode 6.0で追加された国旗の絵文字は、2文字の国コードリストから構成されますが、UTF-16では2文字ともサロゲートペアとなるため、NSString型では4文字としてカウントされます。それに対してString型では、正しく1文字とカウントされます(Unicodeは当初全ての文字を2バイトで表現することを目的としていましたが、近年新たにUnicodeに組み込みたい文字が増えてきたため領域が不足してきました。そのため、新たに追加する文字を4バイトで管理する仕組みとして、サロゲートペアが考案されました)。

リスト25:国旗の絵文字は何文字になるか?

var str = "🇯🇵" // U+1F1EF + U+1F1F5(strは日本の国旗の絵文字だが、環境によってはJPと表示される)
print((str as NSString).length) // -> NSString型では4文字
print(str.count) // String型では1文字

コレクションについて

Swiftでは、コレクションとして配列(Array)、辞書(Dictionary)、集合(Set)といった構造体が用意されています。これらは、それぞれObjective-Cで使用されていたFoundationフレームワークのNSArray(およびNSMutableArray)、NSDictionary(およびNSMutableDictionary)、NSSet(NSMutableSet)といったクラスを置き換えるものです。またSwiftでは、フレームワークではなく、言語に組み込まれた構造体として定義されています。コレクション全体については連載が進むにつれて詳しく説明することにして、ここでは配列(Array構造体)を簡単に紹介しましょう

配列を使ってみる

Foundationフレームワークの配列の場合、ミュータブルな配列はNSMutableArrayクラス、イミュータブル(変更できない)な配列はNSArrayクラスと個別に用意されていました。それに対してSwiftでは、varで宣言すればミュータブル、letで宣言すればイミュータブルになります。配列リテラルの書式はObjective-Cと同じく、要素をカンマで区切り、全体を「[ ]」で囲みます。

リスト26:配列リテラルの書式

// ミュータブルな配列を宣言
var countries = ["アメリカ", "日本", "中国", "イギリス"]
// 2番目の要素を変更する
countries[1] = "ドイツ"

for~inループで配列の要素をイテレートできます。

リスト27:配列の要素をイテレート

for c in countries {
        print(c)
}

実行結果
アメリカ
ドイツ
中国
イギリス

タプルについて

Objective-Cにはない、一連のデータを管理する機能として、Swiftには「タプル(tuple)」があります。タプルとは複数の値をまとめて、一つの値のように扱う仕組みです。Pythonなどのメジャーな言語にも用意されているので、ご存知の方も多いでしょう。タプルのリテラルは次のような書式になります

(値1, 値2, 値3, ...)

値は型が異なっていても構いません。次に、顧客の番号、名前、年齢を管理するタプルcustomerを、型アノテーション付きで宣言する例を示します。

リスト28:タプルの宣言例

var customer:(Int, String, Int) = (101, "江藤三四郎", 43)

型アノテーションを省略しても構いません。

リスト29:型アノテーションを省略した宣言例

var customer = (101, "江藤三四郎", 43)

タプルの各要素には、「変数名.番号」でアクセスできます(番号は先頭の要素を0とする整数値)。

リスト30:タプルの要素へのアクセス

print(customer.1) // -> 江藤三四郎
customer.2 = 44 // 3番目の要素を44に変更

それぞれの要素に名前を付ける

値の前に「名前:」を記述することにより、それぞれの要素に名前を付けることができます。

リスト31:タプルの要素に名前を付ける

var customer = (number:101, name:"江藤三四郎", age:43)

以上で、「変数名.要素名」でアクセスでます。

リスト32:要素名を用いてアクセス

var hisName = customer.name // nameをhisNameに代入
customer.age = 44 // ageを44に変更

タプルの値をそれぞれ変数に代入する

タプルの要素の値を個別の変数に代入するには、左辺の「( )」内にカンマで区切って変数を記述します。

リスト33:タプルの要素を個別の変数に代入

var customer = (number:101, name:"江藤三四郎", age:43)
var (number, name, age) = customer

このとき値が不要な要素は、その部分にアンダースコア「_」を記述します。

リスト34:不要な要素は「_」を記述

var colors = ("red", "blue", "green")
var(c1, _, c3) = colors // c1に"red", c3に"green"が代入される

東京都生まれ。早稲田大学理工学部卒業後、外資系コンピューターメーカーにSEとして8年間勤務。現在はフリーランスのテクニカルライター、プログラマー。

<主な著書>
きちんとわかる! JavaScript とことん入門(技術評論社)
基礎Python(インプレス)
他多数

連載バックナンバー

開発言語技術解説
第6回

Swiftの関数の基本的な取り扱い

2018/6/13
連載の6回目となる今回は、Swiftにおける関数の基本的な扱い方について説明する。
開発言語技術解説
第5回

Swiftのオプショナル型の使いこなし

2018/3/8
連載の5回目となる今回は、値がないことを示すnilを扱えるオプショナル型変数について解説する。
開発言語技術解説
第4回

Swiftの変数の宣言とデータ型について

2018/2/1
Swiftの変数の宣言とデータ型を、Objective-Cと比較しながら解説します。

Think IT会員サービス無料登録受付中

Think ITでは、より付加価値の高いコンテンツを会員サービスとして提供しています。会員登録を済ませてThink ITのWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

他にもこの記事が読まれています