🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1364閲覧

ダウンキャストするメリット

momokoko

総合スコア38

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/01/20 13:16

編集2021/01/21 11:02

Udemyで以下のようなお手本コードがあったのですが、as! ProfileCellでダウンキャストをしなくてもビルドできました。

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ProfileCell return cell }

上記のコードだけでは今回のダウンキャストするメリットはわからないかもしれませんが、一般的にダウンキャストするメリットはどのようなものがあるのでしょうか。

将来的に、自分自身でコードを書くときために知りたいです。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/01/20 13:32

メリットというか、そうしないといけない必要性があるからするということです。しないで済めばそれに越したことはありませんが。
TsukubaDepot

2021/01/21 10:35

横からすみません。 > momokoko さん 具体的に疑問に思った「ダウンキャスト」の例をご提示いただいた方がいいかと思います。 「こういう処理でダウンキャストしていたけど、その理由がわからない」と具体的な例を挙げられた方が、より適切な回答がつくかと思います。 あるいは、「こうなると思ってダウンキャストしたらエラーになった」でも構わないと思います。
momokoko

2021/01/21 10:41

hoshi-takanoriさん、 ダウンキャストの考え方が知れました。 ありがとうございます。 もう少し踏み込んで知りたいことがあるので、質問を修正させていただきます。 TsukubaDepotさん、 アドバイスありがとうございます!
guest

回答1

0

ベストアンサー

たしかに、

Swift

1 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 2 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ProfileCell 3 return cell 4 }

このコードだけ実行しても、ダウンキャストの意味はわからないと思います。
また、ダウンキャストさせる型である ProileCell の作りによっては、ダウンキャストをしなくても動作には影響がない可能性もあります。

そういう意味では、ここで無理にダウンキャストする必要はありません。

しかし、たとえば次の様な型を考えてみたいと思います。

Swift

1class ProfileCell: UICollectionViewCell { 2 var text: String = "" 3}

上記のコードは、CollectionView に表示させるためのカスタムセルの例です。
本来はもっと色々な処理を入れることもありますが、説明を簡単にするためにあえてプロパティを一つのみにしておきたいと思います。

ここで重要なのは、ProfileCell というカスタムクラス(独自の型)は、UICollectionViewCell を継承している、ということです。

つまり、UICollectionViewCell の様々なプロパティやメソッドを引き継いだ上で、新たにtext というプロパティを含んだ型を ProfileCell として作った、と考えていいと思います。

その後、このカスタムクラスを CollectionView のセルとして利用するため、

Swift

1 collectionView.register(ProfileCell.self, forCellWithReuseIdentifier: "cell")

このような感じで登録することになります(StorBoardで登録させた場合には、このコードは必ずしも出てくるわけではありません)。

さて、ここで登録したセルは、実際に表示する際に呼び出す必要があるのですが、その時に使うメソッドが

Swift

1 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)

の一行になるわけです。

ただし、注意したいのは、dequeueReusableCell(withReuseIdentifier:for:) というメソッドの戻り値は、UICollectionViewCell という型である、という点です。

Dequeues a reusable cell object located by its identifier.

上記のリファレンスを読んでいただいてもいいと思いますし、Xcode のヘルプ機能を使っても見ることができるので、一度見てみていただけますでしょうか。

さて、上記のメソッドが返す型は UICollectionViewCell です。なので、実は最初に登録した ProfileCell という型として見えていない、という問題が発生します。

具体的に何が起きるかというと、下記の様なコードを実行しようとした場合に、コメントした部分でエラーが出てしまいます。

Swift

1 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) 2 cell.text = "abcde" // ここでエラーになる

登録した時には ProfileCell というクラスで登録し、そのクラスには text というプロパティがあるにもかかわらず、それを見ることができないわけです。

dequeueReusableCell(withReuseIdentifier:for:)UICollectionViewCell というクラスしか返さないため、どうにかして ProfileCell として利用する方法を考える必要があります。

その時に使う演算子が、ダウンキャスト演算子(as?もしくはas!)となるわけです。

ダウンキャストするというのはどういうことかというと、与えられた元の型(スーパークラスや親クラスと言ったりします)を、そのクラスを引きついたサブクラスとして変換する処理のことです。

つまり、下記のようにダウンキャストを入れることによって、クラスの依存関係を適切に変更することができるようになる、という仕組みです。

Swift

1 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ProfileCell 2 cell.text = "abcde" // エラーは出ないし、Xcode の補完も効くようになる

ちなみに、ダウンキャストは必ずしも成功するとは限りません。

クラスに継承関係がある場合には成功しますが、継承関係にないクラスの間でダウンキャストを行うと失敗するようになっています(as? で処理するか、as! で処理するかによって失敗時の挙動がことなります)。

なぜ失敗を知る必要があるのか、という話になると、これまた適用場面も考え方も違ってきますのでここでは省きますが、とりあえずダウンキャストというのは、このような目的で使っている、とう点だけ抑えていただければと思います。

投稿2021/01/21 13:16

TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momokoko

2021/01/21 13:37

例まで作成いただきまして丁寧な解説ありがとうございます。 いま、頭が回っていないので明日ゆっくり読み、理解したいと思います。
momokoko

2021/01/23 09:20 編集

ありがとうございます! 難解な文章かなと思っていましたが、スラスラ読むことができました。 特に例が理解の助けとなりました。 以下、学んだことを自分の理解となりますが整理のためにまとめさせていただきます。 ダウンキャストする理由 ・カスタムクラスのプロパティにdequeueReusableCellメソッドからアクセスできないから 詳細 ・registerでProfileCell型のセルを登録 ・dequeueReusableCellの返り値はUICollectionViewCell ・子から親のプロパティにアクセスできるが、親から子のプロパティにはアクセスできない  ・子の型にダウンキャストする
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問