Swift 5.8 日本語化計画 : Swift 5.8


型キャスト


値の実行時の型を決定し、より具体的な型情報を与えます。


型キャスト(タイプキャスト) は、インスタンスの型をチェックし、または独自のクラス階層内の別の場所から別のスーパークラスまたはサブクラスとしてそのインスタンスを扱うための方法です。


Swift の型キャストは、isas 演算子として実装されています。これら2つの演算子は、値の型を確認するか、別の型に値をキャストするためのシンプルで表現豊かな方法を提供します。


また、プロトコル準拠の確認 で説明したように、型がプロトコルに準拠しているかどうかチェックするために型キャストを使用することもできます。



型キャストのためのクラス階層の定義


特定のクラスインスタンスの型をチェックし、同じ階層内の別のクラスにそのインスタンスをキャストするクラスとサブクラスの階層で型キャストを使用できます。以下の3つのコードスニペットは、クラスの階層と型キャストの例で使用するためのそれらのクラスのインスタンスを含む配列を定義しています。


最初のスニペットは MediaItem という新しい基本クラスを定義します。このクラスは、デジタルメディアライブラリに表示された項目の全ての種類の基本的な機能を提供しています。具体的には、String 型の name プロパティと init(name:) イニシャライザを宣言しています。(これは、すべての映画や曲を含むすべてのメディア項目は、名前を持っていると想定しています。)


  1. class MediaItem {
  2. var name: String
  3. init(name: String) {
  4. self.name = name
  5. }
  6. }


次のスニペットは MediaItem の2つのサブクラスを定義しています。最初のサブクラス、Movie は、映画やフィルムに関する追加情報をカプセル化します。対応するイニシャライザで、基本の MediaItem クラスの最上部に director プロパティを追加します。第二のサブクラス、Song は、基底クラスの最上部に、artist プロパティとイニシャライザを追加します。


  1. class Movie: MediaItem {
  2. var director: String
  3. init(name: String, director: String) {
  4. self.director = director
  5. super.init(name: name)
  6. }
  7. }
  8. class Song: MediaItem {
  9. var artist: String
  10. init(name: String, artist: String) {
  11. self.artist = artist
  12. super.init(name: name)
  13. }
  14. }


最後のスニペットは、2つの Movie インスタンスと3つの Song インスタンスを含む library と言う定数の配列を作成します。library 配列の型は、配列リテラルの内容でそれを初期化することにより推測されます。Swift の型チェッカーはその MovieSongMediaItem の共通のスーパークラスを持っている事を推測することができ、それで library 配列の [MediaItem] 型を推測します:


  1. let library = [
  2. Movie(name: "Casablanca", director: "Michael Curtiz"),
  3. Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
  4. Movie(name: "Citizen Kane", director: "Orson Welles"),
  5. Song(name: "The One And Only", artist: "Chesney Hawkes"),
  6. Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
  7. ]
  8. // the type of "library" is inferred to be [MediaItem]


library に格納されている項目は、舞台裏ではまだ MovieSong インスタンスです。しかし、この配列の内容を繰り返し処理した場合、受け取る項目は MediaItem としての型であり、MovieSong としてではありません。それらの特有の型としてそれらを処理するには、下記のように、それらの型を チェック して、または別の型にそれらを ダウンキャスト する必要があります。



型のチェック


インスタンスが特定のサブクラスの型であるかどうかをチェックするためには 型チェック演算子 (is) を使用して下さい。インスタンスがそのサブクラスの型であれば、型チェック演算子は true を返し、そうでない場合、false を返します。


以下の例では、library 配列内の MovieSong のインスタンスの数を数える2つの変数、movieCountsongCount を定義しています。


  1. var movieCount = 0
  2. var songCount = 0
  3. for item in library {
  4. if item is Movie {
  5. movieCount += 1
  6. } else if item is Song {
  7. songCount += 1
  8. }
  9. }
  10. print("Media library contains \(movieCount) movies and \(songCount) songs")
  11. // prints "Media library contains 2 movies and 3 songs"


この例は、library 配列内のすべての項目を反復処理します。各パスで、for-in ループは配列内の次の MediaItemitem 定数を設定します。


item is Movie は、現在の MediaItemMovie インスタンスの場合 true を返し、そうでない場合、false を返します。同様に、item is Song は項目が Song インスタンスであるかどうかをチェックします。for-in ループの終わりに、movieCountsongCount の値は、各型の MediaItem インスタンスがどれだけ多く発見されたかの数を含んでいます。



ダウンキャスト


特定のクラスの型の定数または変数は、実際には舞台裏ではサブクラスのインスタンスを参照しているかもしれません。このような場合、型キャスト演算子 (as? または as!) でサブクラス型に ダウンキャスト しようとすることができます。


ダウンキャストは失敗することがあるので、型キャスト演算子は、二つの異なる形式で提供されます。条件付きの形式は、as? で、ダウンキャストしようとしている型の optional の値を返します。強制的な形は、as! で、ダウンキャストを試み、単一の複合アクションとして結果を強制開封します。


ダウンキャストが成功するかどうかわからない時には、型キャスト演算子 (as?) の条件付き形式を使用して下さい。演算子のこの形式は、常に optional の値を返し、ダウンキャストが不可能であった場合、値は nil になります。これで、ダウンキャストが成功したかどうかをチェックできます。


ダウンキャストが常に成功すると確信している場合にのみ、型キャスト演算子の強制的な形式 (as!) を使用して下さい。正しくないクラス型へダウンキャストしようとした場合、演算子のこの形式は、実行時エラーを引き起こします。


以下の例では、library 内の各 MediaItem を反復処理し、各項目の適切な説明を出力します。これを行うには、単に MediaItem としてではなく、真の MovieSong として各項目にアクセスする必要があります。その説明で使用するための MovieSongdirectorartist プロパティにアクセスできるようにするためにこれは必要です。


この例では、配列内の各項目は、Movie である場合もあれば、Song である場合もあります。各項目に使用する実際のクラスは、事前にはわからないので、ループを通じて毎回ダウンキャストをチェックするには、型キャスト演算子 (as?) の条件付きの形を使用することが適切です:


  1. for item in library {
  2. if let movie = item as? Movie {
  3. print("Movie: \(movie.name), dir. \(movie.director)")
  4. } else if let song = item as? Song {
  5. print("Song: \(song.name), by \(song.artist)")
  6. }
  7. }
  8. // Movie: 'Casablanca', dir. Michael Curtiz
  9. // Song: 'Blue Suede Shoes', by Elvis Presley
  10. // Movie: 'Citizen Kane', dir. Orson Welles
  11. // Song: 'The One And Only', by Chesney Hawkes
  12. // Song: 'Never Gonna Give You Up', by Rick Astley


この例では、Movie として現在の item をダウンキャストしようとして始まります。itemMediaItem インスタンスなので、それは Movie かも しれません。同じように、それはまた Song かもしれませんし、あるいは基本の MediaItem かもしれません。この不確実性のため、as? 形式の型キャスト演算子は、サブクラス型にダウンキャストしようとすると optional の値を返します。item as? Movie の結果は、Movie? 型か、または "optional の Movie" です。


library 配列内の Song インスタンスに適用された場合には Movie にダウンキャストする事は失敗します。これに対処するため、上記の例では、optional の Movie が、実際に値を含む (つまり、ダウンキャストが成功したかどうかを調べる) か確認するために、optional の結合を使います。この optional の結合は "if let movie = item as? Movie" と書かれており、こう読めます:


"Movie として item にアクセスしてみました。これが成功すれば、戻された optional の Movie に格納されている値に movie と言う新しい一時的定数を設定します。" と。


ダウンキャストが成功すると、movie のプロパティは、その director の名前を含め、その Movie インスタンスの説明を印刷するために使用されます。同様の原理は、Song> インスタンスをチェックするためと、そして Song が library で発見されるたびに (artist 名を含む) 適切な説明を印刷するために使用されます。



注意: キャストは実際にはインスタンスを変更したり、その値を変更しません。基本となるインスタンスは同じままで、単純に処理され、型のインスタンスは、それがキャストされた型としてアクセスされます。


Any と AnyObject 用の型キャスティング


Swift は、非特定の型を操作するための二つの特別な型を提供します。


明示的にそれらが提供する動作や能力を必要な場合にのみ、AnyAnyObject を使用してください。コード内で動作するように期待する型について特別であるのが常により良い事です。


ここで関数型と非クラス型を含む、異なる型の混合で動作するように Any を使用する例を挙げます。この例では、Any 型の値を格納できる things と言う配列を作成します。


  1. var things = [Any]()
  2. things.append(0)
  3. things.append(0.0)
  4. things.append(42)
  5. things.append(3.14159)
  6. things.append("hello")
  7. things.append((3.0, 5.0))
  8. things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
  9. things.append({ (name: String) -> String in "Hello, \(name)" })


things 配列は、2つの Int 値、2つの Double 値、一つの String 値、(Double,Double) 型のタプル、映画 "ゴーストバスターズ"、および String 値を取り、別の String 値を返すクロージャ式を含んでいます。


Any または AnyObject 型のいずれかでしかないと知られている定数または変数の特定の型を発見するには、switch 文の case の isas パターンを使う事ができます。以下の例は、things 配列内の項目を繰り返し処理し、switch 文で各項目の型を照会します。switch 文の case のいくつかは、その値を印刷するのを有効にするために、指定された型の定数に、その一致した値を結合します:


  1. for thing in things {
  2. switch thing {
  3. case 0 as Int:
  4. print("zero as an Int")
  5. case 0 as Double:
  6. print("zero as a Double")
  7. case let someInt as Int:
  8. print("an integer value of \(someInt)")
  9. case let someDouble as Double where someDouble > 0:
  10. print("a positive double value of \(someDouble)")
  11. case is Double:
  12. print("some other double value that I don't want to print")
  13. case let someString as String:
  14. print("a string value of \"\(someString)\"")
  15. case let (x, y) as (Double, Double):
  16. print("an (x, y) point at \(x), \(y)")
  17. case let movie as Movie:
  18. print("a movie called \(movie.name), dir. \(movie.director)")
  19. case let stringConverter as (String) -> String:
  20. print(stringConverter("Michael"))
  21. default:
  22. print("something else")
  23. }
  24. }
  25. // zero as an Int
  26. // zero as a Double
  27. // an integer value of 42
  28. // a positive double value of 3.14159
  29. // a string value of "hello"
  30. // an (x, y) point at 3.0, 5.0
  31. // a movie called 'Ghostbusters', dir. Ivan Reitman
  32. // Hello, Michael


注意: Any 型は、optional 型を含む任意の型の値を表します。Swift は、Any 型の値が期待される所で optional の値を使用すると、警告を表示します。optional 値を Any 値として使用する必要が実際にある場合は、as 演算子を使用して、以下に示すように Any に optional を明示的にキャストできます。

  1. let optionalNumber: Int? = 3
  2. things.append(optionalNumber) // Warning
  3. things.append(optionalNumber as Any)     // No warning



前:同時実行 次:ネストした型
















トップへ












トップへ












トップへ












トップへ
目次
Xcode の新機能

Swift について
Swift と Cocoa と Objective-C (obsolete)
Swift Blog より (obsolete)

SwiftLogo
  • Swift 5.8 全メニュー


  • Swift へようこそ
  • Swift について
  • Swift 言語のガイド
  • Swift の基本
  • 基本演算子
  • 文字列と文字
  • コレクション型
  • フロー制御
  • 関数
  • クロージャ
  • 列挙型
  • 構造体とクラス
  • プロパティ
  • メソッド
  • サブスクリプト
  • 継承
  • 初期化
  • デイニシャライザ
  • Optional の連鎖
  • エラー処理
  • 同時実行
  • 型キャスト
  • ネストした型
  • 拡張機能
  • プロトコル
  • ジェネリック(汎用)
  • 不透明な型
  • 自動参照カウント
  • メモリの安全性
  • アクセス制御
  • 高度な演算子

  • 言語リファレンス

  • マニュアルの変更履歴













  • トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ