タイプ・キャスト
ここではあるタイプから、あるタイプへのキャストを行なう方法を紹介します。
そして、あるオブジェクトが特定のタイプであるかどうか調べるための演算子について説明します。
オブジェクトの性質を調べつつ、安全なタイプキャストを行なうことは非常に重要です。
is 演算子
ある特定のオブジェクトが、あるクラスのオブジェクトであるかどうか調べるには is 演算子が使えます。
次の例では、Any タイプの配列に String 型, Int 型, Bool 型の三つの要素を追加しています。
var a = [Any]()
a.append( "Hello" )
a.append( 5 )
a.append( true )
print( a )
for item in a {
if item is String {
print( "\(item)" )
}
}
["Hello", 5, true] Hello
for-in ループを用いて、それらの要素を順番に取り出して is を用いて String であるかどうかチェックし、String ならそれを出力しています。
as? と as!
タイプキャストを行なう時には、二つの形式があります。
ひとつはコンディショナル・フォームの as? で、もうひとつはフォースト・フォームの as! です。
? と ! の違いは、オプショナルであるか、あるいは、強制的であるかということの違いです。「強制アンラッピングとオプショナル・チェイン」でも ? や ! がそうでしたね。
as? でキャストを試みた場合は、それがキャストできなければ単に nil が返ります。一方、as! でキャストを試みると、キャストが出来ない場合はランタイムエラーが発生します。
次の例では、上と似たような例になりますが AnyObject の配列にオブジェクトを入れて、for-in ループでそれぞれの要素を取り出し、as? で Person 型へのキャストを試みています。もし、Person 型であれば、"Hello, (名前)!" という文字をプリントしています。
class Dog {
var name = "Pochi"
}
class Person {
var name : String
init( _ name : String ){
self.name = name
}
}
class Employee : Person {
override init( _ name : String ){
super.init( name )
}
}
var a = [AnyObject]()
a.append( Dog() )
a.append( Person( "Ichiro" ) )
a.append( Employee( "Hanako" ) )
for item in a {
if let p = item as? Person {
print( "Hello, \(p.name)" )
}
}
Hello, Ichiro Hello, Hanako
ちなみに、上の例で出てきた Any や AnyObject についても簡単に補足しておきます。
Any 型、AnyObject 型は不特定型 (non-specific type) と呼ばれています。AnyObject 型は class 型のオブジェクトを保持でき、Any 型では全ての型を保持できます。