0Pricing
Swift Academy · レッスン

as?による条件付きキャスト

失敗時にoptionalを返すキャストを試します。

「as?による条件付きキャスト」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

条件付きキャスト

条件付きキャスト演算子as?はダウンキャストを試み、オプショナルを返します。成功した場合は値がラップされ、失敗した場合はnilになります。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let maybe = a as? Dog
print(maybe != nil)

結果はオプショナル

キャストは失敗する可能性があるため、結果の型はDogではなくDog?です。使用する前にアンラップする必要があります。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let maybe: Dog? = a as? Dog
print(type(of: maybe))

if let によるアンラップ

as?の慣用的な使い方は、if letによるバインディングの中で使うことです。キャストが成功した場合だけ本体が実行されます。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
if let dog = a as? Dog {
    print(dog.bark())
} else {
    print("Not a dog")
}

失敗したキャストは nil を返す

インスタンスが対象の型でない場合、as?はnilを返し、if letの本体はスキップされます。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Cat(name: "Mia")
if let dog = a as? Dog {
    print(dog.bark())
} else {
    print("That is not a dog")
}

guard let と組み合わせる

guard letを使って早い段階でキャストし、失敗した場合は終了することもできます。これにより、通常の処理のインデントを深くせずに済みます。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
func describe(_ a: Animal) {
    guard let cat = a as? Cat else {
        print("Not a cat")
        return
    }
    print(cat.meow())
}
describe(Cat(name: "Mia"))
describe(Dog(name: "Rex"))

ループ内での条件付きキャスト

異なるサブクラスが混在する配列を反復処理し、各要素を条件付きでキャストすると、安全にサブクラスごとの処理を行えます。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let zoo: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia"), Dog(name: "Buddy")]
for a in zoo {
    if let dog = a as? Dog {
        print(dog.bark())
    }
}

プロトコルへのキャスト

as?はプロトコルへの適合も確認します。インスタンスがプロトコルに適合していれば値を返し、そうでなければnilを返します。

protocol Greeter { func greet() -> String }
class Person: Greeter { func greet() -> String { return "Hi" } }
class Rock {}
let items: [Any] = [Person(), Rock()]
for item in items {
    if let g = item as? Greeter { print(g.greet()) }
}

キャスト後の nil 合体

as?と??演算子を組み合わせると、キャストに失敗した場合の代替値を指定できます。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Cat(name: "Mia")
let sound = (a as? Dog)?.bark() ?? "unknown sound"
print(sound)

オプショナルなキャスト呼び出しの連鎖

オプショナルチェーンを使うと、キャスト結果に対してメソッドを呼び出せます。キャストに失敗すると、式全体がnilになります。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let a: Animal = Dog(name: "Rex")
let bark = (a as? Dog)?.bark()
print(bark as Any)

条件付きキャストが推奨される理由

as?はクラッシュしません。キャストに失敗しても単にnilを生成します。そのため、ダウンキャストでは安全なデフォルトの選択肢になります。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let unknown: Animal = Cat(name: "Mia")
let result = unknown as? Dog
print("Crashes? No. Value is nil:", result == nil)

条件付きキャストのまとめの例

ここまでの内容を組み合わせると、サブタイプを安全に検出し、それに応じた処理を行い、それ以外の場合は適切に代替処理へ移行できます。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
func sound(of a: Animal) -> String {
    if let d = a as? Dog { return d.bark() }
    if let c = a as? Cat { return c.meow() }
    return "silence"
}
print(sound(of: Dog(name: "Rex")))
print(sound(of: Cat(name: "Mia")))

確認問題

条件付きキャストの結果の型を思い出してください。

復習:as? による条件付きキャスト

as?は安全なダウンキャストを行い、オプショナルを返すこと、if letとguard letで成功時の値をアンラップできること、そして失敗すると単にnilになるためクラッシュせず、ダウンキャストに推奨される演算子であることを学びました。

class Animal {
    let name: String
    init(name: String) { self.name = name }
}
class Dog: Animal {
    func bark() -> String { return name + " says Woof" }
}
class Cat: Animal {
    func meow() -> String { return name + " says Meow" }
}
let pets: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
for p in pets {
    if let d = p as? Dog { print(d.bark()) } else if let c = p as? Cat { print(c.meow()) }
}

よくある質問

「as?による条件付きキャスト」レッスンは無料ですか?

はい。「as?による条件付きキャスト」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「as?による条件付きキャスト」で何を学びますか?

失敗時にoptionalを返すキャストを試します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「as?による条件付きキャスト」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. アップキャストとダウンキャストの基礎
  2. as?による条件付きキャスト
  3. as!による強制キャストとそのリスク
  4. isによる型の確認
← Swift Academyに戻る