みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Java 「参照型の型変換」について

Java初心者です。

入門書を読んでいたら、「参照型の型変換」を説明している項目に
以下の方法で行うと書いてありました。

==前提===
Personは親クラス
Employeeは小クラス
Engineerは孫クラス
========
(1)Engineer型からPerson型へ暗黙の型変換する場合
Person per1 = new Engineer();

(2)Person型からEngineer型へキャストする場合
Engineer eng1 = (Engineer) per1;

(3)Person型からEmployee型へキャストする場合
Employee emp1 = (Employee) per1;
========

これ、変換の方法は上記で分かったのですが、

そもそも、

"何のために参照型の型変換を行うのか"
"型変換を行うと、それぞれのオブジェクトの機能がどのように変わるのか"

そういった説明が一切書いておらず、その意味するところが理解出来ませんでした。

スーパークラス型からサブクラス型にキャストする場合、
サブクラス型からスーパークラス型に暗黙の型変換する場合、
それぞれのオブジェクトの性質がどう変化するのでしょうか?
メソッドやフィールドに対しての挙動が何か変わるのでしょうか?

基本データ型の型変換は分かり易いんですけどね。。

参照型はどうにも。。

教えて下さい!

投稿日時 - 2011-05-01 23:13:17

QNo.6707894

すぐに回答ほしいです

質問者が選んだベストアンサー

これは、親、子、孫、のように一直線のクラスだけを考えるとあまりありがたみがありません。親から2種類以上の子がでてくるとありがたみがでます。
例えばPersonを親として、Employee、Studentという子クラスがあったとします。
で、EmployeeもStudentも同じように変数で捕まえておきたい場合にPersonを使うことができるのです。

Person papa = new Employee();
Person boku = new Student();

papa や boku は 同じ型(Person)なので、Personのメソッドが使えます。さらにvirtual なメソッドを定義しておけば、同じように扱うことができます。
例えば、Employee型には、CompanyName というメソッドがあり Student 型には SchoolName というメソッドがあったとしても、同じPerson型で受けることができるわけです。そしてPersonにBelongNameというvirtualなメソッドを用意しておいて、Employee のときは CompanyName を StudentのときはSchoolName を返すようにしておけば、Person 型の papa や boku から同じ名前のBelongNameというメソッドでそれぞれ最適なメソッドを呼び出すことができます。

こうすることで、すっきりわかりやすいプログラミングができるのです。上記の例は単純ですが、私はこの機能こそがクラスの継承の醍醐味だと考えています。

投稿日時 - 2011-05-01 23:49:49

補足

早速のご回答ありがとうございます!

すみません、「virtualなメソッド」とはどういったものの事を言うのでしょうか?
参考書にも載っておらず。。。
その後の説明頂いた部分が理解出来ませんでした。。。

また、
>papa や boku は 同じ型(Person)なので、Personのメソッドが使えます。
これについては、
EmployeeもStudentもPersonを継承していた場合、

Employee papa = new Employee();
Student boku = new Student();

という書き方でも、
親に当たるPersonのメソッドは全く同じように利用可能ですよね??

質問ばかりで申し訳ないです。

投稿日時 - 2011-05-02 00:16:13

ANo.1

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

#1です。
すみません、「virtualなメソッド」とはどういったものの事を言うのでしょうか?
参考書にも載っておらず。。。
その後の説明頂いた部分が理解出来ませんでした。。。
>>この回答は、#2さんのとおりです。

また、
>papa や boku は 同じ型(Person)なので、Personのメソッドが使えます。
これについては、
EmployeeもStudentもPersonを継承していた場合、

Employee papa = new Employee();
Student boku = new Student();

という書き方でも、
親に当たるPersonのメソッドは全く同じように利用可能ですよね??

>この場では、確かにpapa の宣言をEmployee型にしてもStudent型にしても大差ないです。
これら、papaとbokuを#3さんがおっしゃっているようにリストとか配列にいれたいとき何型で宣言しますか?
こういう場合に継承が有効になるのです。つまり、共通するPerson型の配列を作っておけばEmployee型もStudent型も入れることができるのです。これが継承の利点です。





質問ばかりで申し訳ないです。

投稿日時 - 2011-05-06 16:42:29

ANo.3

例えば Employee が給与計算用メソッド calcSalary を持っていたとします。
孫に Engineer と Managerが有るとすると、おそらく給与計算方法はかなり異なるでしょう。
しかし、calcSalaryのインターフェースは工夫すれば全く同じにできるでしょう。

このように、内容は異なるが意味的には同じ処理を見つけてインターフェースを合わせてゆく
設計作業を共通性ー可変性分析と言います。このような設計がなされていると、
後で、Employee の孫に Secretary が加わって、給与計算方法が違っても、
共通のインターフェースを使って実装すれば、既存のコードにほとんど
影響を与えません。細かな処理の違いは孫クラスの個々の処理が受け持ち、
上位の処理は Employee の メソッドで処理を進めることができます。

これをもし、変数の型を Engineer とか Secretary とか書いてしまったら広範囲に
改造が及ぶことになるでしょう。上位の処理内容が全く同じでも、別々にコードを
書く破目になります。


ダウンキャストですが、これは上位のインターフェースではなくて、クラスのより具体的な
メソッドに上位からアクセスしなければならないときに使います。

これは使わざる得ない時もあるのですが、悪い兆候でもあります。出来るだけ使わないように
工夫するのが無難です。

投稿日時 - 2011-05-02 14:14:05

ANo.2

あんまりいい例じゃないけど:
Employeeクラスのオブジェクトを引数に持つメソッド
aMethod(Employee employee)
には Employeeクラスのオブジェクトでも Engineerクラスのオブジェクトでも渡すことができます. そして, このメソッドの内部ではどちらのオブジェクトであっても Employeeクラスのオブジェクトとして扱われ, Employeeクラスのインスタンスメソッド (とそのスーパークラスである Personクラスのインスタンスメソッド) を呼び出すことはできますが, Engineerクラスのインスタンスメソッドは (たとえ実際に渡したのが Engineerクラスのオブジェクトであったとしても) 呼び出すことはできません.

#1 の virtual は, ここで「Employeeクラスのインスタンスメソッドを呼び出すときに, 実際に呼び出されるメソッドがどれか」を指定する用語です. 「常に Employeeクラスのインスタンスメソッドが呼び出される」なら nonvirtual, 「実際のオブジェクトのクラスに従って (つまりもともと Employeeクラスのオブジェクトなら Employeeクラスの, もとが Engineerクラスのオブジェクトなら Engineerクラスの) インスタンスメソッドが呼び出される」なら virtual です... が, Java のメソッドは全部 virtual なのでここはあんまり気にしなくていいです.

この辺は「単独のデータとして持つ」ときには無視していいんですが, 「複数のデータがあってそれらを一括して管理する」ときには重要です. 例えば「全従業員のリスト」を考えると
List<Employee>
を使うことになり, このリストには Employeeクラスのオブジェクトと Engineerクラスのオブジェクトを混在することができます (そしてそれらは全て「Employeeクラスのオブジェクト」として扱われる).

投稿日時 - 2011-05-02 01:10:12

あなたにオススメの質問