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 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.
スウィフトでの型キャストは、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
プロパティを加えます。第二のサブクラス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:
最終的な断片はlibrary
と呼ばれる定数の配列をつくります、それは、2つのMovie
インスタンスと3つのSong
インスタンスを含みます。library
配列の型は、ある配列リテラルの内容でそれを初期化することから推論されます。スウィフトの型チェッカーは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](「library」の型は、[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
インスタンスです。しかし、あなたがこの配列の内容上に繰り返すならば、あなたがそこから取り出す項目は、MediaItem
型としてであって、Movie
またはSong
ではありません。それらをそれらの生来の型として取り扱うために、下で述べるように、あなたはそれらの型を調べること、またはそれらを異なる型へダウンキャストすることが必要です。
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:
下の例は2つの変数、movieCount
とsongCountを
定義します、それは、Movie
とSong
インスタンスの数をlibrary
配列において数えます:
- 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"(「情報媒体書庫は、2つの映画と3つの歌を含みます」を出力します)
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:
Movie
にダウンキャストすることは、library配列のSong
インスタンスに適用されるとき失敗します。これに対処するために、上の例は、オプショナル束縛を使って、オプショナルの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
がlibraryで見つけられるときはいつでも、適切な説明(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: スウィフトは、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
を使う例が、ここにあります。この例はthings
と呼ばれる配列をつくります、それは、Any
型の値を格納することができます:
- 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
値を返す1つのクロージャ式を含みます。
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
のものであることだけが知られている定数や変数の具体的な型を見つけるために、あなたはis
またはas
パターンをswitch
文のケース節の中で使うことができます。下の例は、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(整数値の42)
- // a positive double value of 3.14159(正の浮動小数点の値の3.14159)
- // a string value of "hello"(文字列値の「よろしく」)
- // an (x, y) point at 3.0, 5.0(3.0、5.0の(x, y)座標点)
- // 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
が期待されるところで使うならば警告を与えます。あなたが本当にオプショナル値をAny
値として使う必要があるならば、あなたはas
演算子を使って明示的にオプショナルをAny
へキャストすることが、以下で示すように行えます。
- let optionalNumber: Int? = 3
- things.append(optionalNumber) // Warning(警告)
- things.append(optionalNumber as Any) // No warning(警告なし)