質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

90.47%

  • Java

    14116questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

[Java] ダウンキャストの仕組みについて

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 5,531

k499778

score 501

現在Java Silverの資格を取るために黒本を勉強しています。
そこでダウンキャストの理解についてつまづいてしまいました。

以下のコードは実行時に例外がスローされ、ClassCastExceptionが発生します。
そうなるのはわかったのですが、なぜそうなるかがわかりません。


public class aa{

    public static void main(String[] args){

    cc c=new cc(){};
    bb b= (bb)c;

    }
}


class bb extends cc{
}

class cc{
    void b(){
        System.out.println("ccクラスです。");
    }
}


黒本 p277にはbbインスタンスにはccインスタンスの差分が含まれていないため、例外が発生する。
といったようなことが書いています。

そうすると以下は差分がないため、例外が発生しないような気がするのです。
もしくはデフォルトコンストラクタがその差分に当たるのでしょうか?

もしそうなら継承の関係においてダウンキャスト時に例外がスローされないケースはあるのでしょうか?

そもそも私の黒本の解説の解釈に少し誤りがあるのでしょうか?

いまいちスッキリ理解できていないのでもし分かる方がいれば教えていただきたいです。

実際の試験時は「継承のダウンキャストは実行時に例外が発生する」ととりあえず解答しようと思いますが、このままだと腑に落ちないし、もしそうでないときもあるのならと思い、しっかり理解したいと思いました。



追記
class A{
    void hello(){
        System.out.println("A");
    }
}

class B extends A{
    void hello(){
        System.out.println("B");
    }
}

public class Main{
    public static void main(String[] args){
    A a=new A();
    B b= (B)a;
    b.hello();
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

ダウンキャストで例外が発生しない例は以下の様なものがあります.
public class aa{

    public static void main(String[] args){

    cc c=new bb(); //ccの代わりにbbのコンストラクタ
    bb b= (bb)c;

    }
}
bbのインスタンスを生成してそのスーパークラス型のcc型の変数に入れる段階でアップキャストが発生します.その後bbへのダウンキャストを行っています.
この場合cの実体はbbクラスのインスタンス(アップキャストしようが実体は変わらない)なので,例外は発生せずキャストができます.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/26 23:10

    swordoneさん
    回答ありがとうございます。
    おっしゃるとおりですね。そのパターンがありましたか。
    確かにアップキャストしたものをダウンキャストするときにキャスト式を明示的に書き、
    なおかつ例外は発生しませんね。

    知りたかったことが知れました。
    ありがとうございます。
    感謝しています。

    キャンセル

+2

黒本 p277にはbbインスタンスにはccインスタンスの差分が含まれていないため、例外が発生する。
[...]
そもそも私の黒本の解説の解釈に少し誤りがあるのでしょうか?
黒本とやらの解説は不正確、好意的に解釈しても誤解を与える表現になっています。

ダウンキャスト/アップキャストの動作を理解する際は、ソースコード上に記述されている「静的な型」と、プログラム実行時に決まるインスタンス自身の「動的な型」を区別して認識すべきです。
// スーパークラスB を継承した サブクラスD を定義
class B { /*...*/ }
class D extends B { /*...*/ }

D d1 = new D();  // OK
// d1の静的な型D/動的な型D
B b1 = d1;  // OK: 暗黙のアップキャスト
// b1の静的な型B/動的な型D
D x = (D)b1;  // OK: ダウンキャスト
// xの静的な型D/動的な型D

B b2 = new B();
// b2の静的な型B/動的な型B
D y = (D)b2;  // NG: ダウンキャスト → ClassCastException例外が送出される
// yの静的な型D には 動的な型Bを持つインスタンスを保持できない


他回答コメントに書かれた内容から、該当文脈での"差分"という用語の使われ方を理解できました。
継承は「差分プログラミング」という手法で、サブクラスのインスタンスは、スーパークラス内に記述されている処理内容とサブクラス内に記述されている処理内容(差分)の両方を持っている。
上記の引用文それ自身は、概ね正しいことを言っています。もう少し詳細化するならば次の通りでしょうか。

 継承とは「差分プログラミング」という考え方を、Java言語において実装する手法であり、サブクラスのインスタンスは、スーパークラス内に記述されている処理内容とサブクラス内に記述されている処理内容(差分)の両方を持っている。この実装手法によって、サブクラスではスーパークラスの処理内容を繰り返して記述する必要がなく、処理内容の追加/変更を行いたい差分だけを記述するという差分プログラミングを実現できる

そして、この話と「ダウンキャストの成功可否」には直接的な関係はありません。ダウンキャスト操作に関係するのは「キャスト先の変数の型は何か?キャスト元のインスタンスの型は何か?」という2点だけです。

差分プログラミングはプログラムの設計思想や設計方針について述べたものであり、一方のダウンキャスト操作では単にJava言語仕様を対象とした議論をしています。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/27 02:08

    yohhoyさん
    回答ありがとうございます。
    これはどういうことでしょうか?
    変数名とインスタンス生成のこのyohhoyさんが書いてくださったパターンを区別して
    3つ目のときは例外が発生するという風に理解すればいいということでしょうか?
    差分うんぬんは置いといて。
    もう継承でダウンキャスト時は、一部の場合を除いて、例外が発生すると覚えてしまった方がいいのかなあ。

    キャンセル

  • 2015/09/27 10:25

    乱暴な理解でよければ「ダウンキャスト操作は常に失敗の危険が伴う。ダウンキャストに成功するのはごく限られた状況のみ。」で良いでしょう。これは少し大げさですが、「ダウンキャストが必要になった=クラス設計が不適切である兆候」とも言えます。

    変数の型(静的な型)とインスタンスの型(動的な型)について、体系的に整理して理解されることをお勧めします。関連するJava言語機能として「instanceof演算子」「ジェネリクス」が挙げられます。

    キャンセル

  • 2015/09/27 11:00 編集

    回答追記しました。(異なるレイヤの概念を混同されているように思えます)

    キャンセル

  • 2015/09/27 13:35

    yohhoyさん
    追加回答ありがとうございます。
    すごく詳しい説明ありがとうございます。

    理解できたと同時に、とりあえず理解の導入として「ダウンキャスト操作は常に失敗の危険が伴う。ダウンキャストに成功するのはごく限られた状況のみ。」とまずは考えようと思います。


    他の方にも質問させていただいたのですが、

    以下のサイトの最後の方にある
    http://www.kab-studio.biz/Programing/OOPinJava/08/05.html
    >なぜなら、インスタンスの中にキャスト先の型のインスタンスは含まれていないのですから。

    という考え方をするのはどうでしょうか?


    この考え方でいくと
    ・通常のダウンキャストはキャスト元のインスタンスの中にキャスト先の型のインスタンスが含まれていないから失敗する。
    ・一部のダウンキャスト(アップキャストしてからダウンキャストするswordoneさんの回答にある内容)はキャスト元のインスタンスの中にキャスト先の型のインスタンスが含まれているから成功する。

    と考えることができてスッキリ理解することができます。
    そのような理解の仕方は間違っているでしょうか?

    私の中では差分の考え方と似ているのですが、機能拡張の差分ではなく、インスタンスの有無という視点で捉えているので、この理解の仕方や伝え方だといいのかなあと思っています。

    もしお時間あればお答えいただけると幸いです。

    キャンセル

  • 2015/09/28 14:03

    > 以下のサイトの最後の方にある
    > http://www.kab-studio.biz/Programing/OOPinJava/08/05.html
    >> なぜなら、インスタンスの中にキャスト先の型のインスタンスは含まれていないのですから。
    > という考え方をするのはどうでしょうか?

    キャスト操作の挙動説明としては誤っていないので、そのような解釈を行っても問題無いとは思います。

    # 余談:この説明はインスタンス/オブジェクトの物理的なイメージからのアプローチですね。一方で、オブジェクト指向の教科書に出てくる「インスタンス/オブジェクト間のis-a関係やhas-a関係」といった論理的な関係性からアプローチする説明もありますから、並行して理解されると良いのではないでしょうか。

    キャンセル

checkベストアンサー

+1

class bb extends cc{
    public bb(){
       super();
    }
}

class cc{
     public cc(){
       super();
    }
    void b(){
        System.out.println("ccクラスです。");
    }
}
コンストラクタを追記しました。
・ccのコンストラクタ:super()を呼ぶことでObjectクラスのコンストラクタを呼び出しています。
・bbのコンストラクタ:super()を呼ぶことでccクラスのコンストラクタを呼び出しています。
つまりccのコンストラクタは「Object型のインスタンス」+「cc型のインスタンス」を作ります。
一方でbbのコンストラクタは「cc型のインスタンス」+「bb型のインスタンス」を作ります。

それを踏まえると下記のようになります。
bb b = new bb();
cc c = (cc) b;//bb型として作られたインスタンスbはcc型のインスタンスと差分が無い部分が存在するためキャストできる。
c = new cc();
bb b = (bb)c;//cc型として作られたインスタンスcはbb型のインスタンスと差分が無い部分が存在しないためキャストできない。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/26 23:04

    yonaさん
    回答ありがとうございます。
    やはり差分というのは具体的にいうとデフォルトコンストラクタになるということでしょうか?
    http://www.javadrive.jp/start/constructor/index4.html

    まさにyonaさんや上記のリンク先が書いている通り、
    コンストラクタを明示的に定義しない場合はデフォルトコンストラクタとして
    yonaさんが追記してくださったコードが自動的に追加され、それがbbクラスとccクラスで差分となり、キャストに失敗している。そのデフォルトコンストラクタが黒本でいう差分にあたる。と考えていいのでしょうか?
    デフォルトコンストラクタの場合アクセス修飾子がパッケージプライベートとなるのでpublicとなっている点が気になりますが、デフォルトコンストラクタのことだと勝手に解釈しています。

    少し長くなりましたが、そういう認識で捉えてよろしいのでしょうか?
    もしお時間ございましたら返答頂けると嬉しいです。

    キャンセル

  • 2015/09/26 23:50

    bbインスタンスにはccインスタンスの差分が含まれていないので…
    この記述は正しいですか?できたら回答をそのまま書いていただけないでしょうか?

    継承関係を取れるならアクセス修飾子はどれでも一緒です。

    キャンセル

  • 2015/09/27 02:46

    yonaさん
    追加回答ありがとうございます。
    実際の問題は上に追記したソースコードで、これをコンパイル、実行したときどうなるかといった内容です。答えは「実行時に例外がスローされる」です。

    この解説が以下です。
    「変数aの参照先にあるインスタンスは、Aのインスタンスです。AのインスタンスにはBの差分が含まれていないため、Bでオーバーライドしたメソッドを実行できません。AのインスタンスをBのインスタンスに変換することはできません。そのため、コンパイルは問題なく通りますが、実行すると型の変換に失敗した旨の例外がスローされます。キャストは「扱い方」を変える、つまり変数の型を変えるだけで、参照先にあるインスタンスの種類を変更できるわけではないことに注意してください。
    以上のことから、『実行時に例外がスローされる』が正解です。」


    私はこの問題については理解できました。
    hello()の処理内容が違うので、AのインスタンスにはBの差分(サブクラスで新たに定義した内容のこと)が含まれていないため、実行すると型の変換に失敗した旨の例外がスローされるのだなと。

    そして新たに疑問が生じました。
    「じゃあ差分がなければ例外はスローされないのか?」と。
    そこで試したのが投稿したソースです。
    予想では、「差分がないので解説の論理からいくと例外はスローされない」でした。
    しかし、例外はスローされました。

    なぜだろうと思い、自分で考えてもわからないので、teratailに投稿しました。
    「なぜ差分がないのに例外がスローされたのか?解説の理論通りにいかない」
    「もしくは差分があってそれがデフォルトコンストラクタなのではないか?」
    「そもそもこの解説の私の解釈が間違っていて、違う理由で例外がスローされているのか?」

    黒本の問題通りの内容でなく、それを少し拡張した内容でした。
    また黒本の解説を抜粋する部分や解釈の仕方がまずく、みなさんを混乱させてしまったのかもしれません。

    私は黒本の解説を読み、「スーパークラスとサブクラスの差分があることがダウンキャスト時に例外をスローさせている」という風に捉え、投稿に事細かに全文載せたり経緯をいちいち説明するのもバツが悪いと思い、あのような投稿になりました。

    もしかしたらみなさんをミスリードしてしまっていたかもしれません。

    これが経緯であり、それを踏まえた上で
    「なぜダウンキャスト時に例外がスローされるのか」を知りたいです。
    デフォルトコンストラクタがその差分になっているからなのでしょうか?
    もはや差分とかの問題ではないのでしょうか?

    長文失礼いたしました。

    キャンセル

  • 2015/09/27 10:09

    横から失礼します.
    差分うんぬんは例外が発生する理由(なぜそうしてはいけないか)のわかりやすい事例で,実際は差分のあるなしではなく,単にそのサブクラスのインスタンスを持っているかということで判定しているに過ぎないと思います.
    見ようによっては黒本に載っていたというコードも「差分なし」と解釈できます(hello()というメソッドしか持っていないという点で)し,もっと言うとサブクラスのhello()メソッドが
    void hello(){
    super.hello();
    }
    という書き方なら完全に差分なしとも考えられます.
    JVMがキャスト時にいちいちそんなチェックはしていられないので,単にそのインスタンスの実体がどうかで例外を投げたり投げなかったりということをしているのだと思います.

    キャンセル

  • 2015/09/27 12:18

    経緯は理解しました。

    いろいろと理解するポイントがずれていますね。

    クラスキャストエクセプションの発生理由は差分があるかどうかではありません。
    ・キャスト
    クラスAのインスタンスを別のクラスBのインスタンスとする。
    ・キャスト出来るかどうか
    クラスAの継承関係やインターフェース実装等を考慮して、クラスBにすることができるかを判定します。
    ・キャスト出来た場合
    以降キャストしたインスタンスはクラスBのインスタンスとして使用できる。
    ・キャスト出来なかった場合
    クラスキャストエクセプションが発生する。

    では差分とは何か?
    差分プログラミング等で使われている差分と同義だと思います。
    決して、クラスAをコピーしてクラスBを作成した結果、2つのクラスには差分が無いと言っているわけでありません。
    クラス構造的な意味で差分が無いと言っていることに注意してください。

    キャンセル

  • 2015/09/27 13:14

    yonaさん
    追加回答ありがとうございます。
    継承における差分という考え方はキャストとは直接関係ないということが理解することができました。

    言語仕様やyohhoyさんのおっしゃる通り「キャスト先の変数の型は何か?キャスト元のインスタンスの型は何か?」という2点だけで判定しているのですね。

    ほぼほぼスッキリ理解することができました。


    くどいですが、もうひとつだけつっこませてください。もしお忙しいようであればスルーしていただいて構いません。

    私の中でスッキリしきれない理由が、唯一成功する「アップキャストしてからダウンキャストする」ケースです。swordoneさんの回答にあります。

    もちろんインスタンスがダウンキャスト時に一致しているので成功するのはわかるのですが、「ダウンキャストは基本失敗する。しかし一部成功する」の一部成功する理由を理解したいのです。

    以下のサイトの最後の方にある
    http://www.kab-studio.biz/Programing/OOPinJava/08/05.html
    >なぜなら、インスタンスの中にキャスト先の型のインスタンスは含まれていないのですから。

    という考え方でいくと、
    ・通常のダウンキャストはキャスト元のインスタンスの中にキャスト先の型のインスタンスが含まれていないから失敗する。
    ・一部のダウンキャストはキャスト元のインスタンスの中にキャスト先の型のインスタンスが含まれているから成功する。

    と考えることができてスッキリ理解することができます。
    そのような理解の仕方は間違っているでしょうか?

    何度もすいません。

    キャンセル

  • 2015/09/27 13:24

    下記の理解の仕方はいかがでしょうか。

    ・別の型に変換することをキャストという。
    ・キャストが成功し、継承関係を上に辿ることをアップキャスト
    ・キャストが成功し、継承関係を下に辿ることをダウンキャスト
    ・キャストが失敗するとクラスキャストエクセプションが発生する。

    キャンセル

  • 2015/09/27 13:26

    swordoneさん
    回答ありがとうございます。
    おっしゃるとおりですね。
    JVMの視点の内容も書いていてくれて理解が深まりました。
    ありがとうございます。

    キャンセル

  • 2015/09/27 13:42

    yonaさん
    回答ありがとうございます。
    そうですね。その点については私もスッキリ理解できています。その通りだと思います。

    その一歩踏み込んだ内容、より具体的な細かいところの理解の仕方が「キャスト先とキャスト元のインスタンスの有無」だとどうかなあと思っていました。

    これは間違っていないのかなあという気がするのです。

    ただ個人的な考え方の部分にもなってくる微妙な箇所かもしれませんね。

    多くの回答いただきありがとうございました。
    感謝しています。

    キャンセル

  • 2015/09/27 14:08 編集

    私は下記のように理解しています。

    ・クラスAをインスタンス化するとメモリ上に領域が確保されます。

    ・クラスAを継承したクラスBをインスタンス化するとメモリ上に、クラスAの領域を確保した後にクラスBの領域を確保する。

    メモリ上の領域にアクセスするためには、適切な型で宣言された参照変数が必要になります。このメモリ上の領域をプログラマーの責任で広げたり、狭めたりする行為がキャストです。

    ざっくり言うとインスタンスの有無で合っていますね。

    キャンセル

  • 2015/09/27 19:11

    yonaさん
    回答ありがとうございます。
    その言葉が聞けて私もやっと確証をもってこの考え方でいこうと思うことができました。ありがとうございます。

    yonaさんの説明してくださっているメモリの確保とその後サブクラスのインスタンスの領域を確保するという説明も理解できます。私もその認識です。
    考えのつじつまが合い、スッキリ理解することができました。
    何度にもわたる質問をしてしまったことをお許しください。そしてありがとうございました。
    yonaさん感謝しています。ありがとうございました。

    キャンセル

+1

黒本を読んだことが無いので、その本で言っている「差分」の定義がどんなものかは分かりません。また、正確なJava言語仕様上の定義も分かりませんが、
bbクラスは、「ccクラスを継承した新しいクラス」という点が機能の差分となっていると考えられます。


本題とはあまり関係ないかもしれませんが、
new cc(){}ccクラスの匿名サブクラスのインスタンス生成になっています。
これは意図的なものでしょうか?


(追記)

最初と言っていることが変わってしまいますが...


差分というのは、おそらくJava以外の言語(C++ とか?)の継承のケースのことを言っているのではないかと思いました。ただ、この辺はあまり詳しくないので自信はないです。

Java言語仕様のことではなく、たとえのような意味でいっているとしたらそれはそれで語弊があるような気もします。


言語仕様に拠れば、Javaの場合は、差分でなく、主に継承関係のチェックだけでダウンキャスト(Narrowing Reference Conversion)が可能かをチェックしています。


言語仕様の最新版(Java8)は英語ですが下記です。(5.1.6)
Chapter 5. Conversions and Contexts - Java Languate Specification

日本語版は少し古いですが、下記ページの「5.1.5 参照型の縮小変換」を参照して下さい。
Java言語規定 変換及び昇格

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/26 22:57

    arguisさん
    回答ありがとうございます。

    > new cc(){}はccクラスの匿名サブクラスのインスタンス生成になっています。
    失礼しました。匿名サブクラスのインスタンス生成になっていますね。
    new cc()の誤りです。すいません。以後気をつけます。

    キャンセル

  • 2015/09/26 23:13 編集

    >bbクラスは、「ccクラスを継承した新しいクラス」という点が機能の差分となっていると考えられます。

    やはりその差分というのは言葉では「ccクラスを継承している点」ですが、
    具体的にコードでいうと、インスタンス生成時に自動的に追加されるデフォルトコンストラクタがbbクラスとccクラスで違う部分のことになるのでしょうか?

    キャンセル

  • 2015/09/26 23:49

    すみません、もう一度考えてみたら最初の回答がしっくりいかなかったので、追記しました。

    キャンセル

  • 2015/09/27 02:59 編集

    arguisさん
    追加回答ありがとうございます。

    「差分」は説明不足だったかもしれません。
    黒本で、よく使われていた言葉だったので慣れてしまっていました。

    「差分」とは「サブクラス内で記述されている処理内容」です。

    継承は「差分プログラミング」という手法で、
    サブクラスのインスタンスは、スーパークラス内に記述されている処理内容と
    サブクラス内に記述されている処理内容(差分)の両方を持っている。

    と黒本には書かれています。


    ただarguisさんがおっしゃってくださったように
    差分がどうとかではなく、ダウンキャストの例外に関しては継承関係かどうかだけの問題なのかもしれません。

    yonaさんのコメントに黒本に書かれている解説を載せています。
    また質問本文の追記にその問題を載せています。
    あまり気は進みませんでしたが、商業目的でもないですし、ちゃんと書かないとみんながもやもやしたままになってしまうと思い、書かせてもらいました。

    キャンセル

  • 2015/09/27 10:56

    yonaさんのコメント欄のを読みました。

    文脈が正確に分からないと確実ではありませんが、解説は
    「継承してクラスを作ると、差分で機能拡張(メソッドを追加するなど)することができる」とは言っているかも知れませんが、「継承してクラスを作ったとき、機能拡張しなければ差分が無い」とは言っていないように思います。


    最終的には、言語仕様に書いていることを正と考えるべきでしょう。

    キャンセル

  • 2015/09/27 13:24

    arguisさん
    回答ありがとうございます。

    そうですね。黒本には機能拡張しなければ差分がないとは書いていないです。
    その差分がないと判断したのは私です。
    もしくは差分があってそれがデフォルトコンストラクタなのかなとも判断しました。


    おっしゃるとおりです。言語仕様が正ですね。


    arguisさん含めみなさんの回答で差分プログラミングの差分とキャストは直接関係していないということを知ることができました。ありがとうございます。

    ほぼほぼスッキリしているのですが、1つだけスッキリしきれない点があります。

    yonaさんに聞いた内容と同内容になるのですが、
    「アップキャストしてダウンキャストする」唯一ダウンキャストが成功するケースです。

    この唯一成功するメカニズムを理解したく、調べていて以下のサイトがありました。
    http://www.kab-studio.biz/Programing/OOPinJava/08/05.html

    この最後の方にある考え方がしっくりハマりました。
    >なぜなら、インスタンスの中にキャスト先の型のインスタンスは含まれていないのですから。

    この考え方でいくと、

    ・通常のダウンキャストはキャスト元のインスタンスの中にキャスト先の型のインスタンスが含まれていないから失敗する。
    ・一部のダウンキャストはキャスト元のインスタンスの中にキャスト先の型のインスタンスが含まれているから成功する。

    と考えることができてスッキリ理解することができます。
    そのような理解の仕方は間違っているでしょうか?

    もしお時間あればお答えいただけると幸いです。


    キャンセル

  • 2015/09/27 13:50

    おおむね正しいかと思います。
    ただ、参考にされているページの「インスタンスの中にある型」という表現には少し違和感があります。
    「インスタンスそのものの型」といった方がしっくりきます。

    インスタンスそのものの型は常に変わらず、互換性のある型の変数に代入できる、というのがJava参照型のキャストの基本です。

    キャンセル

  • 2015/09/27 19:15

    arguisさん
    回答ありがとうございます。
    そのように言っていただきやっとスッキリ理解することができたと思えます。
    たしかに「インスタンスの中にある型」っていう表現は違和感がありますね。「インスタンスそのものの型」の方がしっくりくる気がします。

    arguisさん含め、みなさんのおかげでスッキリ理解することができました。
    ありがとうございました。感謝しています。

    キャンセル

関連した質問

同じタグがついた質問を見る

  • Java

    14116questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。