[swift]コードで見たis,as,as?,as! - Type Casting


Type Casting


Type casting is a way to check the type of an instance, or to treat that instance as a different superclass or subclass from somewhere else in its own class hierarchy.
type castingは、インスタンスタイプを決定したり、インスタンスを他のスーパークラスまたはサブクラスと見なしたりする方法です.

タイプ鋳造のクラス階層の宣言


リファレンス
import Foundation

class MediaItem {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}

class Song: MediaItem {
    var artist: String
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}

「チェックタイプ」(Checking Type)

is演算子を使用して、特定のインスタンスのタイプを決定します.
let library = [
    Movie(name: "Casablanca", director: "Michael Curtiz"),
    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
    Movie(name: "Citizen Kane", director: "Orson Welles"),
    Song(name: "The One And Only", artist: "Chesney Hawkes"),
    Song(name: "Never Gonna Give You Up", artist: "Rick Astley"),
]

var movieCount = 0
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}

print("Media library contains \(movieCount) movies and \(songCount) songs")
// Media library contains 2 movies and 3 songs
ここで、libraryは、MediaItemを含む例を示す.type inferenceとして当然であるが,タイプcastingを扱う際には,不思議に思わなかった.

as演算子の使用


asはすぐにタイプがcastingであるかどうかを通知します.asの実行時間はここで確認できます.
let fly = Movie(name: "Fly!", director: "Ji")

print((fly as MediaItem).name) // Fly!
print((fly as Movie).name) // // Fly!
//print((fly as Song).name) // Cannot convert value of type 'Movie' to type 'Song' in coercion

では、先ほどのlibraryのように(形状を検証するisの方法もある)配列やハッシュテーブルを指定できない場合は、どうすればいいのでしょうか.as?およびas!を使用します.

ちゅうぞう

as?およびas!演算子を使用して、どのタイプのインスタンスであるかを決定します.as?は、特定のタイプが正しいかどうかを判断できない場合に使用され、as!は特定のタイプである場合に使用される.次の例は、library演算子mediaItemを使用して次の鋳造を行う.なぜなら、MovieSongの例であってもよいし、例であってもよいからである.
for item in library {
    if let movie = item as? Movie {
        print("Movie: \(movie.name), dir. \(movie.director)")
    } else if let song = item as? Song {
        print("Song: \(song.name), by \(song.artist)")
    }
}

//Movie: Casablanca, dir. Michael Curtiz
//Song: Blue Suede Shoes, by Elvis Presley
//Movie: Citizen Kane, dir. Orson Welles
//Song: The One And Only, by Chesney Hawkes
//Song: Never Gonna Give You Up, by Rick Astley
鋳造が正常に行われていることを確認します.as?を使用すると、Outshernalが返されます.
print(library[0] as? Movie)
//Optional(TestAndTest.Movie)

as! 演算子の使用


ロールをif letに降格したが、タイプが指定されていない場合は、ランタイムエラーが発生します.
print(library[0] as! Song)
//런타임 에러!!

as, as?, as!差異


コンパイル時、as?わあ!実行時に実行されます.
  • コンパイル時間:ソースコード(swiftファイル)を作成しコンパイルによりマシンコードに変換し、実行可能プログラムの編集プロセス
  • 実行時:コンパイルされたプログラムの実行とアプリケーションの実行が完了した時間
  • reference
    https://zeddios.tistory.com/265
    https://gaki2745.github.io/swift/2019/10/02/Swift-Basic-04/
    https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html