タコさんブログ

プログラミングメモと小言

swift の as as! as? オペレータ (Type Cast Operator) と is (Type Check Operator) とパターンマッチ

環境

as オペレータ

  • Swfitコンパイラにより型変換・キャストが成功すると保証されるときに使用
  • アップキャスト
  • リテラルの型を指定
class Animal {}
class Dog: Animal {}

let dog = Dog()

let animal = dog as Animal // アップキャスト

let floatValue = 1 as Float  // 型指定

as! オペレータ

  • 強制的にダウンキャスト
  • ダウンキャストが成功することが分かっている場合に使用
  • ダウンキャストが失敗するとruntimeエラーになる
let animal1: Animal = Dog()
let dog = animal1 as! Dog // OK

let animal2 = Animal()
let dog2 = animal as! Dog // ダウンキャストできないのでruntimeエラー

as? オペレータ

  • ダウンキャストが成功するか分からない場合に使用
  • 戻り値はオプショナル型
  • 失敗した場合はOptional.None
let animal1: Animal = Dog()
let dog = animal1 as? Dog // dogの型はOptional<Dog>

let animal2 = Animal()
let dog2 = animal as? Dog // エラーは起こらない。dog2の中身は.None

if let dog = dog2 {
    print("dog is not nil")
} else {
    print("dog is nil")
}  // 出力: dog is nil

is 型チェックオペレータ

  • isオペレータはインスタンスがある型のサブクラスの型か判定するときに使用
  • 戻り値はある型のサブクラスの型のとき true, そうでないとき false
let animal = Animal()
let isDog = animal is Dog
print(isDog)  // 出力: false

let dog = Dog()
let isAnimal = dog is Animal
print(isAnimal) // 出力: true

// AnyObject型にしないとコンパイラがSmartすぎて
// 下の警告がでるためAnyObjectにしている:
// 'is' test is always true
let isDog2: AnyObject = dog is Dog
print(isDog2) // 出力: true

as と is パターンマッチ (Type-Casting Patterns)

ややこしことに is, as はswitchのパターンマッチと一緒に使用できる。

class Animal {
  func bark() -> String {
      return "$&%#"
  }
}

class Dog: Animal {
  override func bark() -> String {
    return "woof-woof"
  }
}

let things: [Any] = [0, 0.0, Animal(), Dog()]

for thing in things {
  switch thing {
    // thingがIntか判定。値自体に興味はないときに is を使用する
    case is Int:
      print("thing is Int value")
    case is Float:
      print("thing is Float")
    // thingがDogにマッチするか判定し
    // (asの右側のタイプかそのサブタイプか)、
    // マッチした場合、Dogにキャストされたdogを取得
    case let dog as Dog:
      print("Dog barks " + dog.bark())
    case let animal as Animal:
      print("Animal barks " + animal.bark())
    default:
      print("something else")
  }
}

/*
出力:
  thing is Int value
  thing is Float
  Animal barks $&%#
  Dog barks woof-woof
*/