2019/12/5 Swift オプショナル型 パート1

オプショナル型とは

オプショナル型はジェネリック型の列挙型として定義されていて、

「ある型の値」、あるいは「値が存在しない(nil)」

ということを表す型です。

sample1-1

let str1="777"
let num1=Int(str1)
print(num1)
//Optional(777)

SwiftのInt型にはString型の変数の値をInt型に型変換するイニシャライザがあるのですが、全ての文字列が数値に変換できる訳ではありません。

例えば文字列”777″は数値の777に型変換できますが(sample1-1)、文字列”abc”はInt型に型変換できません。

つまりイニシャライザInt()は必ずInt型に変換した値を返せるとは限らない、し失敗することもある、ということです。ですのでsample1-1の結果が示す通り、イニシャライザInt()はOptional<Int> 型の値を返します。

Optional<Int>型は簡易的な記法としてInt?と記述することもでき、通常こちらの書き方が用いられます。

Optional<Int>=Int?

Int?(Optional<Int>)型は整数の値を保持している、あるいは値がない、ということを表します。

sample1-1では文字列”777″はInt型への型変換が成功しますので、定数num1には列挙型Optional<Int>.some(777)がセットされます。sample1-1の結果にあるようにOptional<Int>.some(777)にも簡易的な記法が用意されており、Optional(777)と記述できます。


nil

sample2-1

var num4:Int?=nil
print(num4)
//nil

Optional型の変数にnilを代入することで、値が存在しないことを表すことができます。


sample2-2

var str1="777"

str1=nil

//error: 'nil' cannot be assigned to type 'String'

オプショナル型でない変数にnilを代入することはできません。なので値がない状態が考えられる変数・定数は必ずオプショナル型として宣言する必要があります。


sample2-3

var num4:Int?
print("num4:\(num4)")
//num4:nil

オプショナル型の変数を初期化せず宣言すると自動的にnilがセットされます。


強制アンラップ

オプショナル型の変数・定数が値を保持していることがわかっている時、変数名(定数名)の直後に ! を置くことで、その値にアクセスすることができます。

sample3-1

var str1="777"
let num1=Int(str1)
print(num1)
print("\(num1!)")
print(type(of:num1!))

//Optional(777)
//777
//Int

nilがセットされているオプショナル型の変数に強制アンラップをすると実行時エラーになります。強制アンラップをするときは、その変数が必ず値を保持している(nilでない)ことを確かめてからにしましょう。

そもそもアンラップとは何かの定義説明。その後強制アンラップの説明。という順序が必要。

Optinal<Int>をアンラップしないとInt型と加算減算できない。


オプショナルバインディング(optional binding)

sample4-1

var var10=Int("778")

先ほど例に出した文字列の型変換で、上記sample4-1では型変換が成功しますし、イニシャライザIntの引数に渡す文字列によっては型変換が失敗することもあります。

変数var10にセットされた値がある場合(つまりnilでない場合)アンラップしてその値を取り出す、値がない場合(つまりnilの場合)は無い場合の処理を行うコードは、

sample4-2

var var10=Int("778")

if var10 != nil{
    print("\(var10!)")
}else{
    print("var10 is nil")
}

//778

上記のようなコードで実現できますが、これをもっとスマートに記述する方法としてオプショナルバインディングがあります。sample4-2をオプショナルバインディングを使用したものがsample4-3です。


sample4-3(オプショナルバインディング)

var var10=Int("778")

if let temp10=var10{
    print("\(temp10)")
}else{
    print("var10 is nil")
}

//778

変数var10はInt?型です。var10に値がある場合Int型の778が定数temp10にセットされます。3行目ではアンラップしていませんが、temp10にはInt型の778がセットされます。それがオプショナルバインディングです。

sample4-4

var var10=Int("cannot convert")

if let temp10=var10{
    print("\(temp10)")
}else{
    print("var10 is nil")
}

//var10 is nil

var10がnilの場合sample4-4のようにelse節が実行されます。


暗黙的アンラップオプショナル型(implicitly unwrapped optional)

これまで説明してきたオプショナル型は(値がある時に)値を取り出す必要がある時、毎回アンラップする必要がありました。しかし「暗黙的アンラップオプショナル型」は値にアクセスするのにアンラップする必要がありません。

通常のオプショナル型(値を取り出すのにアンラップが必要なオプショナル型)は

Int?

のように表しましたが、暗黙的アンラップオプショナル型は、

Int!

のように型名の直後に ! を置いて表します。

sample5-1

let str11:String?="aaaaa"
let var11:String=str11!
print(var11)    //aaaaa

let str2:String!="bbbbb"
let var2:String=str2
print(var2)    //bbbbb

変数str11は通常のオプショナル型ですので、String型の変数var11へ代入するにはアンラップする必要があります。

それに対してstr2は暗黙的アンラップオプショナル型として宣言されていますので、String型の変数var2へ代入する時にアンラップする必要がありません。

6行目でstr2にアクセスした時点で自動的にアンラップされます。

sample5-1ではstr2が”bbbbb”という文字列値を保持していましたので問題はありませんが、仮にstr2がnilの時

 

 

参考

https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html

(Optionals)

 

 

“2019/12/5 Swift オプショナル型 パート1” への1件の返信

コメントを残す

メールアドレスが公開されることはありません。