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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Java

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

Q&A

解決済

2回答

1859閲覧

【java】スーパクラス型でサブクラスのインスタンスを生成した場合のメソッドコールについて

h.miyo

総合スコア1

Java

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

0グッド

0クリップ

投稿2021/01/02 10:06

オブジェクト型のキャストについて

現在Java silverを学習中で、オブジェクト型のキャストについて詰まってしまったので
知識を拝借させていただきたくご質問いたします。

クラスをインスタンス化する際に、スーパクラスの型で、サブクラスのインスタンスを生成し、
サブクラスのメソッドをコールする場合,ダウンキャストをしなければコンパイルエラーが発生
するというのは、理解ができました。

しかし、下記のコードのようにサブクラスにて、スーパクラスのメソッドをオーバライドした場合
は、ダウンキャストせずとも、コンパイルが成功しました。

なぜコンパイルが成功したのかが、理解できず、ご質問させていただきました。

該当のソースコード

java

11class Main { 22 public static void main(String[] args) { 33 Sample obj = new Test(); //スーパクラス型でサブクラスのインスタンスを生成 44 obj.print(); //サブクラスでオーバライドしたメソッドをコール 55 } 66} 7 87class Sample { // スーパクラス 98 public void print() { 109 System.out.println("スーパクラスのメソッド"); 1110 } 1211} 13 1412class Test extends Sample { // サブクラス 1513 public void print() { // スーパクラスのメソッドをオーバライド 1614 System.out.println("サブクラスのメソッド"); 1715 } 1816}

上記コードの8〜10行目を削除して実行すると、コンパイルエラーになります。
※ダウンキャストすれば実行可能です。

私の現時点の知識だと、上記のコードはサブクラスのprintメソッドを実行しており、インスタンスは
スーパクラスなため、ダウンキャストしない限りコンパイルエラーになると思ったのですが、、、、

オーバライドをすると、実装先はオーバライドを記述したサブクラスではなく、スーパクラスになったり
するのでしょうか?
※スーパクラスに実装になれば、コンパイルエラーにならないのも納得ができます。

スーパクラス型でサブクラスのインスタンスを生成した場合の、メソッドコールについて、オーバライド
をした場合、サブクラスのメソッドをダウンキャスト無しでコールしてもコンパイルエラーにならない理由
をご教授いただけると嬉しいです。

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

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

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

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

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

guest

回答2

0

コンピュータの目線で見てください。
Sampleクラスにprintメソッドが記述されていることにより、Sample型のオブジェクトに対してprintというメソッドを実行することができることがわかります。
TestクラスはSampleクラスを継承しており、Sampleクラスの持つメソッドをすべて持つことがわかります。それはつまり、Test型のオブジェクトをSample型として扱っても差し支えないことを意味します。

ここが理解の壁でもあるのですが、集合として捉えるとわかりやすいです。人間が哺乳類の「仲間」であるように、TestクラスはSampleクラスの「仲間」なのです。
私のような人間を、哺乳類として扱えるのと同様に、
Testクラスのインスタンスを、Sample型のオブジェクトとして扱えるのです。

さて、哺乳類ができること…例えば「食べる」という事柄をとっても、種類ごとに食べ方は異なります。これを各クラスで定義し、命じることで各々の動作ができるのです。

投稿2021/01/02 11:01

swordone

総合スコア20669

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

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

h.miyo

2021/01/02 12:12

回答いただきありがとうございます。 ご説明いただいたので理解することができました。
guest

0

ベストアンサー

オーバライドをすると、実装先はオーバライドを記述したサブクラスではなく、スーパクラスになったり

するのでしょうか?

違います。オーバーライドした場合は、変数の型ではなく、オブジェクト自身の型にしたがってメソッドが呼び出されます。

投稿2021/01/02 10:17

maisumakun

総合スコア146018

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

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

maisumakun

2021/01/02 10:25

スーパークラスにprint()メソッドが存在するので、呼ぶ側のコンパイルも問題なく成功します。 抽象メソッドやインターフェースのように、「呼ぶ側の型は宣言だけで実装がない」という使い方すら存在します。
h.miyo

2021/01/02 10:40

ご回答頂きありがとうございます。 オーバライドした場合に限り、オブジェクト自身の型(この場合はTest)でメソッドコールされているということですが、この場合のオブジェクトとは私の理解では、3行目のobjがそれにあたりと解釈しております。 となると、Sample型になってしまうと思うのですが。。。 知識不足で、教えていただいた内容が理解できず申し訳ございません。。。 どうしても私の理解では、この例だと、'スーパクラスのメソッド'が出力されるはずだと思ってしまいます。※実際は'サブクラスのメソッド'が出力されます。
maisumakun

2021/01/02 10:55

> オーバライドした場合に限り、オブジェクト自身の型(この場合はTest)でメソッドコールされているということですが そうではありません。メソッド呼び出しは「コンパイル時には変数の型で解決されて」「実行時にはオブジェクトの型で解決される」ということで一貫しています。 オーバーライドしていないメソッドも、オブジェクトの型で呼ばれますが、実装自体が継承されているので、スーパークラスの実装がそのまま使われます。
maisumakun

2021/01/02 10:55

> この場合のオブジェクトとは私の理解では、3行目のobjがそれにあたりと解釈しております。 objという変数の型はSampleですが、中身のオブジェクトの型はTestです。
h.miyo

2021/01/02 12:42

回答いただきありがとうございます。 ご説明いただいたので理解することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問