0Pricing
Swift Academy · レッスン

as!による強制キャストとそのリスク

キャストが必ず成功すると保証できる場合にのみ、as!を使用します。

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

強制キャスト

強制キャスト演算子as!は、ダウンキャストとアンラップを1つの手順で行います。オプショナルではない型を直接取得できますが、キャストに失敗するとクラッシュします。

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 dog = a as! Dog
print(dog.bark())

オプショナルでラップされない結果

as?とは異なり、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 = Dog(name: "Rex")
let dog: Dog = a as! Dog
print(type(of: dog))

as! のリスク

インスタンスが実際には対象の型でない場合、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 = Dog(name: "Rex")
// let cat = a as! Cat  // would crash at runtime
print("Only force-cast when certain")

強制キャストが安全な場合

as!は、型が絶対に正しいと確信できる場合にのみ使用してください。たとえば、直前にisで確認した場合です。

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 a is Dog {
    let dog = a as! Dog
    print(dog.bark())
}

保証の後に行う強制キャスト

コードのロジックによって型が保証されている場合、強制キャストでその確信を明示できます。それでも、確信がない場合は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" }
}
func barkIfDog(_ a: Animal) {
    guard a is Dog else { return }
    let dog = a as! Dog
    print(dog.bark())
}
barkIfDog(Dog(name: "Rex"))

as? と as! の比較

as?は安全でオプショナルを返します。一方、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 = Dog(name: "Rex")
let safe = a as? Dog
let forced = a as! Dog
print(safe?.bark() ?? "nil")
print(forced.bark())

コレクションの強制キャスト

array as! [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 animals: [Animal] = [Dog(name: "Rex"), Dog(name: "Buddy")]
let dogs = animals as! [Dog]
for d in dogs { print(d.bark()) }

危険なパターン

誤った要素を含む配列を強制キャストするとクラッシュします。そのため、要素が混在するコレクションでは、各要素に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 animals: [Animal] = [Dog(name: "Rex"), Cat(name: "Mia")]
// let dogs = animals as! [Dog] // would crash on the Cat
for a in animals {
    if let d = a as? Dog { print(d.bark()) }
}

強制アンラップと強制キャスト

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 = Dog(name: "Rex")
let viaOptional = (a as? Dog)!
let viaForce = a as! Dog
print(viaOptional.name, viaForce.name)

ベストプラクティス

基本的にはas?を使用してください。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" }
}
func process(_ a: Animal) -> String {
    if let d = a as? Dog { return d.bark() }
    return "not a dog"
}
print(process(Dog(name: "Rex")))
print(process(Cat(name: "Mia")))

強制キャストのまとめの例

型が確認済みであれば、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 known: Animal = Dog(name: "Rex")
if known is Dog {
    print((known as! Dog).bark())
}

確認問題

強制キャストの危険性について考えてみてください。

復習:強制キャストとそのリスク

as!はダウンキャストしてオプショナルではない型にアンラップしますが、失敗するとクラッシュすること、型が確実な場合(多くはisによる確認の後)にのみ使用すべきこと、そして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 = Dog(name: "Rex")
if a is Dog { print((a as! Dog).bark()) } else { print("safe skip") }

よくある質問

「as!による強制キャストとそのリスク」レッスンは無料ですか?

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

「as!による強制キャストとそのリスク」で何を学びますか?

キャストが必ず成功すると保証できる場合にのみ、as!を使用します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「as!による強制キャストとそのリスク」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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