とまと あんらいぷ…

エンジニアの活動記録とかつぶやきとか

GitHub
スポンサードリンク

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

スポンサードリンク

【C#】virtual(仮想)メソッドをoverrideした時の挙動確認メモ

継承クラス利用時にいつも確かめてしまうこと


C#で継承クラスを作ってメソッドをoverrideする時、
例えば親クラスの型に子クラスのインスタンスを代入するとどうなるのか?
overrideしたメソッドは本当に正しく動くのかな?
とかかなり気になる。

ところで、「仮想メソッド」をキーワードとして調べた時
一緒に「抽象メソッド」なるものがもれなくついてきます。
この抽象メソッドは実態がない、つまりabstract キーワードによって作成するもので
当エントリで扱うvirtualキーワードを使った「仮想メソッド」とは別物なので注意して下さい。

どちらにしても、ふと仮想メソッドや抽象クラスを作成する時に
実行結果が気になってしまい、そのたびに同じようなサンプルプロジェクトを作っている。

何度も何度も作ってるうち、さすがに重い腰を動かしてメモでも取っておかなければ
今後も作り続けるだろうなと反省したのでまとめておきます。



クラス設計


確認するためにクラスを考えてみる。

継承元(Parent)と継承先(Child)の2クラスを作成する

■Parentクラスのメンバ
・Shout:叫ぶ (仮想メソッド)
・ThisShout:Shoutする

■Childクラスのメンバ
・Shout:叫ぶ (オーバーライド)
・ThisShout:Shoutする(親のThisShoutを隠蔽)
・BaseShout:親がShoutする。


ソースコード


ソースコードはこんな感じになりました。

最後の最後でvarなんか使ってしまってるけど
Child型にChildクラスのインスタンスを突っ込んでいます。

ParentにChildを代入するアップキャストとは違って
ダウンキャストは暗黙的にできないんです。
それと、Parent型にChildを入れても、さすがにBaseShoutは呼べませんでした。

実行結果


コマンドラインで出力された結果のコピペです。

hello ! go execution of the virtual method !
---------------------
Parent p = new Parent()
p.Shout();

Parent "Hey!!!"
---------------------
Child c = new Child();
c.Shout();
c.ThisShout();
c.BaseShout();

Child "Hey!!!"
Child "Hey!!!"
Parent "Hey!!!"
---------------------
Parent parent_c = new Child();
parent_c.Shout();
parent_c.ThisShout();
can not BaseShout();

Child "Hey!!!"
Child "Hey!!!"
can not BaseShout();
---------------------
var cast_c = (Child)parent_c;
cast_c.Shout();
cast_c.ThisShout();
cast_c.BaseShout();

Child "Hey!!!"
Child "Hey!!!"
Parent "Hey!!!"
---------------------
続行するには何かキーを押してください . . .

この結果によりクラス継承のキモは
親の型に子のインスタンスを代入した時。

つまり
Parent parent_c = new Child();
これですね。

BaseShoutは呼べない、つまりParent型として認識されているのに
実際にはThisShoutの呼び出しでoverrideされたChildのShoutが呼び出されています。

継承呼び出しを考えるとき
Abstractにしたり、インターフェースを利用したりと悩む場面はありますが
基本的にはソースコードを分けずに同じような呼び出しの実装が可能だ。
ということです。
▼この記事を読んだ方は、こんな記事も読んでいます。▼

スポンサードリンク

テーマ:プログラミング - ジャンル:コンピュータ

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://dalmore.blog7.fc2.com/tb.php/83-f272c42c
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。