型キャスト
日本語を消す 英語を消す下記URLから引用し、日本語訳をつけてみました。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/typecasting
Determine a value’s runtime type and give it more specific type information.
値の実行時の型を特定し、より具体的な型情報を与えます。
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 in Swift is implemented with the is
and as
operators. These two operators provide a simple and expressive way to check the type of a value or cast a value to a different type.
Swift の型キャストは、is
演算子と as
演算子を使用して実装されます。 これら 2 つの演算子は、値の型を確認したり、値を別の型にキャストしたりするための、シンプルかつ表現力豊かな方法を提供します。
You can also use type casting to check whether a type conforms to a protocol, as described in Checking for Protocol Conformance.
「プロトコル準拠の確認」で説明されているように、型キャストを使用して、型がプロトコルに準拠しているかどうかを確認することもできます。
Defining a Class Hierarchy for Type Casting
型キャストのクラス階層の定義
You can use type casting with a hierarchy of classes and subclasses to check the type of a particular class instance and to cast that instance to another class within the same hierarchy. The three code snippets below define a hierarchy of classes and an array containing instances of those classes, for use in an example of type casting.
クラスおよびサブクラスの階層で型キャストを使用すると、特定のクラス インスタンスの型を確認し、そのインスタンスを同じ階層内の別のクラスにキャストできます。 以下の 3 つのコード スニペットは、型キャストの例で使用するために、クラスの階層とそれらのクラスのインスタンスを含む配列を定義します。
The first snippet defines a new base class called MediaItem
. This class provides basic functionality for any kind of item that appears in a digital media library. Specifically, it declares a name
property of type String
, and an init(name:)
initializer. (It’s assumed that all media items, including all movies and songs, will have a name.)
最初のスニペットは、MediaItem
という新しい基本クラスを定義します。 このクラスは、デジタル メディア ライブラリに表示されるあらゆる種類のアイテムの基本機能を提供します。 具体的には、String
型の name
プロパティと init(name:)
イニシャライザを宣言します。 (すべてのムービーや曲を含むすべてのメディア アイテムに名前があることが想定されています。)
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
The next snippet defines two subclasses of MediaItem
. The first subclass, Movie
, encapsulates additional information about a movie or film. It adds a director
property on top of the base MediaItem
class, with a corresponding initializer. The second subclass, Song
, adds an artist
property and initializer on top of the base class:
次のスニペットは、MediaItem
の 2 つのサブクラスを定義します。 最初のサブクラス Movie
は、映画または映画に関する追加情報をカプセル化します。 これは、基本の MediaItem
クラスの上に、対応するイニシャライザを備えた Director
プロパティを追加します。 2 番目のサブクラス Song
は、基本クラスの上にartist
プロパティとイニシャライザを追加します。
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)
}
}
The final snippet creates a constant array called library
, which contains two Movie
instances and three Song
instances. The type of the library
array is inferred by initializing it with the contents of an array literal. Swift’s type checker is able to deduce that Movie
and Song
have a common superclass of MediaItem
, and so it infers a type of [MediaItem]
for the library
array:
最後のスニペットは、2 つの Movie
インスタンスと 3 つの Song
インスタンスを含む、library
という定数配列を作成します。 library
配列の型は、配列リテラルの内容で初期化することで推測されます。 Swift の型チェッカーは、Movie
と Song
に MediaItem
という共通のスーパークラスがあることを推定できるため、library
配列の [MediaItem]
の型を推測します。
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")
]
// the type of "library" is inferred to be [MediaItem]
The items stored in library
are still Movie
and Song
instances behind the scenes. However, if you iterate over the contents of this array, the items you receive back are typed as MediaItem
, and not as Movie
or Song
. In order to work with them as their native type, you need to check their type, or downcast them to a different type, as described below.
library
に保存されているアイテムは、依然として舞台裏にあるMovie
とSong
のインスタンスです。 ただし、この配列の内容を反復処理すると、返されるアイテムは Movie
や Song
ではなく MediaItem
として型付けされます。 これらをネイティブ タイプとして扱うには、以下で説明するように、タイプを確認するか、別のタイプにダウンキャストする必要があります。
Checking Type
型の確認
Use the type check operator (is
) to check whether an instance is of a certain subclass type. The type check operator returns true
if the instance is of that subclass type and false
if it’s not.
型チェック演算子 (is
) を使用して、インスタンスが特定のサブクラス型であるかどうかを確認します。 型チェック演算子は、インスタンスがそのサブクラス型の場合は true
を返し、そうでない場合は false
を返します。
The example below defines two variables, movieCount
and songCount
, which count the number of Movie
and Song
instances in the library
array:
以下の例では、movieCount
と SongCount
という 2 つの変数を定義しており、library
配列内の Movie
インスタンスと Song
インスタンスの数をカウントします。
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")
// Prints "Media library contains 2 movies and 3 songs"
This example iterates through all items in the library
array. On each pass, the for
–in
loop sets the item
constant to the next MediaItem
in the array.
この例では、library
配列内のすべての項目を反復処理します。 各パスで、for-in
ループはitem
定数を配列内の次の MediaItem
に設定します。
item is Movie
returns true
if the current MediaItem
is a Movie
instance and false
if it’s not. Similarly, item is Song
checks whether the item is a Song
instance. At the end of the for
–in
loop, the values of movieCount
and songCount
contain a count of how many MediaItem
instances were found of each type.
item is Movie
現在の MediaItem
が Movie
インスタンスの場合は true
を返し、そうでない場合は false
を返します。 同様に、「item is Song
」では、アイテムが Song
インスタンスであるかどうかを確認します。 for-in
ループの最後で、movieCount
と songCount
の値には、各タイプで見つかった MediaItem
インスタンスの数が含まれます。
Downcasting
ダウンキャスト
A constant or variable of a certain class type may actually refer to an instance of a subclass behind the scenes. Where you believe this is the case, you can try to downcast to the subclass type with a type cast operator (as?
or as!
).
特定のクラス型の定数または変数は、実際にはバックグラウンドでサブクラスのインスタンスを参照している場合があります。 これが当てはまると思われる場合は、型キャスト演算子 (as?
または as!
) を使用してサブクラス型にダウンキャストしてみてください。
Because downcasting can fail, the type cast operator comes in two different forms. The conditional form, as?
, returns an optional value of the type you are trying to downcast to. The forced form, as!
, attempts the downcast and force-unwraps the result as a single compound action.
ダウンキャストは失敗する可能性があるため、型キャスト演算子には 2 つの異なる形式があります。 条件付きフォーム as?
は、ダウンキャストしようとしている型のオプションの値を返します。 強制形式「as!
」はダウンキャストを試み、結果を単一の複合アクションとして強制的にアンラップします。
Use the conditional form of the type cast operator (as?
) when you aren’t sure if the downcast will succeed. This form of the operator will always return an optional value, and the value will be nil
if the downcast was not possible. This enables you to check for a successful downcast.
ダウンキャストが成功するかどうかわからない場合は、型キャスト演算子の条件付き形式 (as?
) を使用します。 この形式の演算子は常にオプションの値を返します。ダウンキャストが不可能な場合、値は nil
になります。 これにより、ダウンキャストが成功したかどうかを確認できます。
Use the forced form of the type cast operator (as!
) only when you are sure that the downcast will always succeed. This form of the operator will trigger a runtime error if you try to downcast to an incorrect class type.
型キャスト演算子の強制形式 (as!
) は、ダウンキャストが常に成功することが確実な場合にのみ使用してください。 この形式の演算子では、間違ったクラス型にダウンキャストしようとすると、ランタイム エラーが発生します。
The example below iterates over each MediaItem
in library
, and prints an appropriate description for each item. To do this, it needs to access each item as a true Movie
or Song
, and not just as a MediaItem
. This is necessary in order for it to be able to access the director
or artist
property of a Movie
or Song
for use in the description.
以下の例では、library
内の各 MediaItem
を反復処理し、各アイテムの適切な説明を出力します。 これを行うには、単なる MediaItem
としてではなく、実際の Movie
または Song
として各アイテムにアクセスする必要があります。 これは、説明で使用するMovie
またはSong
のdirector
またはartist
のプロパティにアクセスできるようにするために必要です。
In this example, each item in the array might be a Movie
, or it might be a Song
. You don’t know in advance which actual class to use for each item, and so it’s appropriate to use the conditional form of the type cast operator (as?
) to check the downcast each time through the loop:
この例では、配列内の各項目はMovie
またはSong
である可能性があります。 各項目にどの実際のクラスを使用するかは事前には分からないため、型キャスト演算子の条件付き形式 (as?
) を使用してループのたびにダウンキャストをチェックするのが適切です。
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
The example starts by trying to downcast the current item
as a Movie
. Because item
is a MediaItem
instance, it’s possible that it might be a Movie
; equally, it’s also possible that it might be a Song
, or even just a base MediaItem
. Because of this uncertainty, the as?
form of the type cast operator returns an optional value when attempting to downcast to a subclass type. The result of item as? Movie
is of type Movie?
, or “optional Movie
”.
この例は、現在のitem
をMovie
としてダウンキャストしようとすることから始まります。 item
は MediaItem
インスタンスであるため、Movie
である可能性があります。 同様に、それがSong
、または単なる基本MediaItem
である可能性もあります。 この不確実性のため、as?
型キャスト演算子の形式は、サブクラス型にダウンキャストしようとするときにオプションの値を返します。 item as? Movie
の結果はMovie?
のタイプ、または「オプションのMovie
」です。
Downcasting to Movie
fails when applied to the Song
instances in the library array. To cope with this, the example above uses optional binding to check whether the optional Movie
actually contains a value (that is, to find out whether the downcast succeeded.) This optional binding is written “if let movie = item as? Movie
”, which can be read as:
ライブラリ配列内の Song
インスタンスに適用すると、Movie
へのダウンキャストが失敗します。 これに対処するために、上記の例では、オプションのバインディングを使用して、オプションの Movie
に実際に値が含まれているかどうかを確認します(つまり、ダウンキャストが成功したかどうかを調べます)。このオプションのバインディングは、「if let movie = item as? Movie
」と書かれています。次のように読むことができます。
“Try to access item
as a Movie
. If this is successful, set a new temporary constant called movie
to the value stored in the returned optional Movie
.”
「item
にMovie
としてアクセスしてみてください。 これが成功した場合は、movie
という新しい一時定数を、返されたオプションの Movie
に保存されている値に設定します。」
If the downcasting succeeds, the properties of movie
are then used to print a description for that Movie
instance, including the name of its director
. A similar principle is used to check for Song
instances, and to print an appropriate description (including artist
name) whenever a Song
is found in the library.
ダウンキャストが成功すると、movie
のプロパティを使用して、そのmovie
インスタンスの説明 (director
の名前など) が出力されます。 同様の原理を使用して、Song
のインスタンスがチェックされ、ライブラリでSong
が見つかるたびに適切な説明(artist
名を含む)が出力されます。
Note
注釈
Casting doesn’t actually modify the instance or change its values. The underlying instance remains the same; it’s simply treated and accessed as an instance of the type to which it has been cast.
キャストによって実際にインスタンスが変更されたり、その値が変更されることはありません。 基礎となるインスタンスは同じままです。 単純に、キャスト先の型のインスタンスとして扱われ、アクセスされます。
Type Casting for Any and AnyObject
Any および AnyObject の型キャスト
Swift provides two special types for working with nonspecific types:
Swift は、非特定型を操作するための 2 つの特別な型を提供します。
Any
can represent an instance of any type at all, including function types.Any
は、関数型を含むあらゆる型のインスタンスを表すことができます。AnyObject
can represent an instance of any class type.AnyObject
は、任意のクラス型のインスタンスを表すことができます。
Use Any
and AnyObject
only when you explicitly need the behavior and capabilities they provide. It’s always better to be specific about the types you expect to work with in your code.
Any
と AnyObject
は、それらが提供する動作と機能が明示的に必要な場合にのみ使用してください。 コード内で使用することが予想される型については、常に具体的にすることをお勧めします。
Here’s an example of using Any
to work with a mix of different types, including function types and nonclass types. The example creates an array called things
, which can store values of type Any
:
ここでは、Any
を使用して、関数型や非クラス型など、さまざまな型を組み合わせて操作する例を示します。 この例では、Any
型の値を保存できる things
という配列を作成します。
var things: [Any] = []
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" })
The things
array contains two Int
values, two Double
values, a String
value, a tuple of type (Double, Double)
, the movie “Ghostbusters”, and a closure expression that takes a String
value and returns another String
value.
things
配列には、2 つの Int
値、2 つの Double
値、1 つの String
値、タイプ (Double
、Double
) のタプル、映画「ゴーストバスターズ」、および String
値を取得して別の String
値を返すクロージャ式が含まれています。
To discover the specific type of a constant or variable that’s known only to be of type Any
or AnyObject
, you can use an is
or as
pattern in a switch
statement’s cases. The example below iterates over the items in the things
array and queries the type of each item with a switch
statement. Several of the switch
statement’s cases bind their matched value to a constant of the specified type to enable its value to be printed:
Any
または AnyObject
型であることだけがわかっている定数または変数の特定の型を検出するには、switch
ステートメントのケースで is
または as
パターンを使用できます。 以下の例では、things
配列内の項目を反復処理し、switch
ステートメントを使用して各項目のタイプをクエリします。 switch
ステートメントのケースのいくつかは、一致した値を指定された型の定数にバインドして、その値を出力できるようにします。
for thing in things {
switch thing {
case 0 as Int:
print("zero as an Int")
case 0 as Double:
print("zero as a Double")
case let someInt as Int:
print("an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
print("a positive double value of \(someDouble)")
case is Double:
print("some other double value that I don't want to print")
case let someString as String:
print("a string value of \"\(someString)\"")
case let (x, y) as (Double, Double):
print("an (x, y) point at \(x), \(y)")
case let movie as Movie:
print("a movie called \(movie.name), dir. \(movie.director)")
case let stringConverter as (String) -> String:
print(stringConverter("Michael"))
default:
print("something else")
}
}
// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called Ghostbusters, dir. Ivan Reitman
// Hello, Michael
Note
注釈
The Any
type represents values of any type, including optional types. Swift gives you a warning if you use an optional value where a value of type Any
is expected. If you really do need to use an optional value as an Any
value, you can use the as
operator to explicitly cast the optional to Any
, as shown below.
Any
タイプは、オプションのタイプを含む任意のタイプの値を表します。 Any
タイプの値が予期される場所でオプションの値を使用すると、Swift は警告を表示します。 本当にオプションの値を Any
値として使用する必要がある場合は、以下に示すように、as
演算子を使用してオプションを明示的に Any
にキャストできます。
let optionalNumber: Int? = 3
things.append(optionalNumber) // Warning
things.append(optionalNumber as Any) // No warning