C++、VB.net、Java、Delphiなど色々なオブジェクト指向言語がありますが、
以下のようなとき、「子クラスのrunメソッド」を実行したとき、
(1)「親」と表示されてから「子」と表示される。
(2)「子」とだけ表示される。
のそれぞれどちらの仕様なのでしょうか?
親クラス
runメソッド
コンソールに「親」と表示
子クラス
runメソッド
コンソールに「子」と表示
※私は、
子クラス側で、わざわざ、super.run と書かずとも、
勝手に「(1)「親」と表示されてから「子」と表示される。」になる言語が多いと認識していたのですが、
誤った認識でしょうか?
(C++は、明示的に親の同名メソッドをコールしなければ、処理が実行されないと認識していますがC++の仕様は少数派でしょうか?多数派でしょうか?)
No.2ベストアンサー
- 回答日時:
派生クラスで基底クラスの関数を上書きした場合は、派生クラスで定義された動作になります。
従って、答えは(2)になります。
基底クラスの動作を残しつつ派生クラスの処理を追加したい場合は、
普通はテンプレートメソッドを適用して基底クラスを設計します。
ただし、仮想になっていないメソッドを上書きするとポインタまたは参照の型によって動作が変わります。
いずれにせよ、明示的に書かない限り(1)の動作はしません。
この回答への補足
C++では、同名メソッドを書くとオーバーライドになるんですね。
驚き&意外です。
子側の関数で、
superclass::run を書く方法以外で、
メソッドの継承はできないのでしょうか??
No.7
- 回答日時:
>私が触ってきた言語では、通常、
>何も書かなくても親の処理が実行され、
>子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。
それが何という言語なのか、興味ありますね。その言語では、下記のような場合にどうやって記述するのでしょう。
[A]親クラスのrunメソッドと全く違うことを子クラスのrunメソッドでやりたい(コンソールに「親」と表示したくない)場合
[B]コンソールに「子」と表示してからコンソールに「親」と表示したい場合
super.run()を明示的に書く言語(C++とかJava)では[B]は明らかですし、[A]もsuper.run()を書かないだけで実現できます。
子側のクラスで「このメソッドはオーバーライドします」と書くと、継承上書きできる仕様でした。
デフォルトが、処理の継承(※処理の追加)で、明示的に継承上書きと書くと、継承上書きになったと記憶しています。
どの言語だったかは覚えていないのですが、
古めのバージョンのpowerbuilderだったような気がします。
でも、皆さんから突っこまれて、なんか記憶に自信がなくなってきました。。
No.6
- 回答日時:
#2です。
>子側の関数で、
>superclass::run を書く方法以外で、
>メソッドの継承はできないのでしょうか??
先に申し上げたとおり、テンプレートメソッドを使います。
// public
Base::Run()
{
// 基底クラスでの処理
・・・
// 派生クラスの処理を呼び出す
OnRun()
}
// protected
Derived::OnRun()
{
// 派生クラスでの処理
}
OnRun関数は仮想関数にして、基底クラスでは何も処理しないで定義します。
実際に行いたい処理を派生クラスで定義します。
派生クラスのインスタンスからRun関数が呼ばれると、
基底クラスのRun関数内の処理が行われた後、派生クラスのOnRun関数が実行されます。
このようなデザインパターンはC++だけでなく、
Java, C#, VB.NETいずれのオブジェクト指向言語でも適用でき、
潰しが利いて大変便利です。
是非とも身に付けられることをお勧めします。
参考URL:http://ja.wikipedia.org/wiki/Template_Method_%E3 …
ありがとうございます。
テンプレートメソッドは、以下のようなときだけ使っていました。
ordered_process {
step1;
step2;
}
step1{
}
step2{
}
/*************************/
例を出して頂いて気づきましたが、
確かに、
step1は親のメソッドにしか実装せず、
逆にstep2を子だけにしか実装しないようにすれば、
(ordered_processをパブリック、step1をprivateにして隠蔽、step2をprotected)
「通常、何も書かなくても親の処理が実行される」
はできそうですね!
ありがとうございます。
No.5
- 回答日時:
> 私が触ってきた言語では、通常、何も書かなくても親の処理が実行され、
> 子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。
その「差分だけ追記」というのが、ちょっと気になります。
あるクラスが100個のメソッドを持っていて、その殆どを使いまわしつつ幾つか機能を追加したクラスを新たに作りたい、というようなケースで、
「継承」の概念を用いて親のメソッドをほとんどそっくり貰ってきて、足りない分は子に追記する、というのが、オブジェクト指向で「差分を追記」と言った場合の意味合いに通常なります。
行単位・文単位ではなく、メソッド単位の追加なんです。
そこが不思議でならないのですが・・・
>#4
> C++にしろ、smalltalkにしろ、自分がぱっと思い当たるもので、上記挙動をする言語はないような。
私も同感です。ちょっと聞いたことがない。Common Lispなんかの例外中の例外を除けば。
う~ん、#4さんも、#5さんも仰っているということは、
私の勘違いだったのかもしれません。
ありがとうございます。
(時間があれば、色んな言語で再確認してみたいと思います。)
No.4
- 回答日時:
回答じゃないけど、
> 私が触ってきた言語では、通常、何も書かなくても親の処理が実行され、
> 子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。
C++にしろ、smalltalkにしろ、自分がぱっと思い当たるもので、上記挙動をする言語はないような。
具体的にどの言語が、そのような挙動を示すか、補足したほうが回答が得られやすいと思います。
ありがとうございます。
どの言語でそうだったか、書ければ書きたかったのですがうろ覚えで書けませんでした...
(vb.netか、powerbuilderか、javaか、delphiのどれかだったとは思うのですが。)
No.3
- 回答日時:
#1です。
> 継承のためには、以下のように書くケースが多いということでしょうか?
あなたの言う「継承」の意味がはっきりしないのですが、子クラスが存在する理由は「親クラスとは微妙に違うことをやりたい」という点にあるので、一般に、親クラスの同名メソッドが勝手に実行されては困ります。
例えば、次の例を考えてみてください。
親クラス:車
accelメソッド
自身の速度を5[m/s]上昇させる
子クラス:トヨタの何とかっていう車、親クラスは「車」
accelメソッド
自身の速度を10[m/s]上昇させる
この場合、子クラスのaccelメソッドを呼び出した時に自動的に親クラスが呼び出されてしまうと、「そこ書いてあること」と「実際に起こること」との間に差が生まれてしまい、可読性を損なう等の問題が発生します。
その為、「わざわざ親クラスを呼び出したい」という場合には、「わざわざそう指定してやる必要がある」というのが、多くの言語でよく採られている方式です。
又、子クラスに「自身の親クラスはhoge型」だと明示するのは、親子関係を生じさせる時点で既にやっていることのように思えます。色々と無駄です。
ありがとうございます。
「親クラスとは微妙に違うことをやりたい」で目的は合っていますが、
私が触ってきた言語では、通常、
何も書かなくても親の処理が実行され、
子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。
なので、今のところ、C++では、
子側の関数で、
superclass::run を書く方法で考えています。
私は、
親クラス:車
speedプロパティ
x
accelメソッド
自身の速度をx[m/s]上昇させる
子クラス:トヨタの何とかっていう車、親クラスは「車」
accelメソッド
(※何も書かなくても、自身の速度をx[m/s]上昇させる)
速度を上昇した後に行う処理を、追記しておく。
という記述方式の言語が多かったです。
(superclass::accelを書く必要がなかったです)
No.1
- 回答日時:
一言で言うと、言語によって違う、ということになります。
又、一般のメソッドと一部の(コンストラクタのような)メソッドとでも違いが生まれます。
ただし、この場合では、「親クラスのrunメソッドが子クラスによってオーバーライドされている」という扱いになるでしょうから、理屈の上では、親クラスのrunメソッドは「呼ばれない」方が正しい実装になるかと思われます。
この回答への補足
ありがとうございます。
継承のためには、以下のように書くケースが多いということでしょうか?
親クラス
runメソッド
コンソールに「親」と表示
子クラス : 親クラスはhoge型
runメソッド : 親クラスはhoge型
コンソールに「子」と表示
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
- Java java 次の機能を有するメソッドを自クラスに作成し、実装したいです。 機能 名前判定機能 →名前が 3 2022/06/16 16:08
- C言語・C++・C# C# 継承の問題で programに示された拡張をすべて含んだ上で,クラス Mammal に,そのオ 1 2022/07/22 09:48
- その他(プログラミング・Web制作) このプログラミングをどう組みますか? Googlecolabでやってるんですが、出来る方お願いします 1 2022/07/13 10:52
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/17 18:41
- JavaScript React と Electron でデスクトップアプリを開発する環境について 1 2023/02/08 11:16
- その他(プログラミング・Web制作) pythonリストの特定の値を表示htmlで表示できない 2 2022/05/14 05:48
- Java コンソールから所属財産を入力(単位:万円 1000~100000以内でIntegerに変換できない場 2 2022/05/31 21:32
- その他(SNS・コミュニケーションサービス) ストーリーを非表示にされました。 今日友達と話していたら、同級生の子にストーリーを非表示にされている 1 2022/04/18 00:42
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「ラッパークラス」の存在意義...
-
C言語のプログラムをJavaに
-
vb.net 自作プロパティの削除に...
-
バックグラウンドでキー監視
-
ファイルパスが取得出来ない(P...
-
C#からDLLを呼びたいのですが・...
-
(vba)他のアプリケーションの右...
-
肥大化した実装クラスを分割す...
-
【C#】クラスのコンストラクタ...
-
interface,extend,implementの...
-
Ftpでの帯域制限の設定方法につ...
-
メソッドの引数にクラス名を渡す
-
オーバーライドとラッパーの違い
-
javaで3D-CAD
-
javaの基本的な質問です
-
エクセルVBAで、条件に一致する...
-
「タイプ初期化子が例外をスロ...
-
private static という変数の修飾
-
レコード件数の表示
-
配列の重複する値とその個数を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
interface,extend,implementの...
-
「ラッパークラス」の存在意義...
-
(vba)他のアプリケーションの右...
-
抽象クラスをJUNITでテストする...
-
オーバーライドとラッパーの違い
-
C# 「データが失なわれる可能性...
-
【C#】クラスのコンストラクタ...
-
JTextFieldの入力制限
-
c++でのヘッダーファイルの循環...
-
「継承されたメソッドの可視性...
-
vb.net 自作プロパティの削除に...
-
ASP.NETでの共通コードの書き方...
-
Javaのインスタンス化の構文の...
-
Javaで下線
-
メソッドの引数にクラス名を渡す
-
VB DLLプロジェクトについて
-
C#からDLLを呼びたいのですが・...
-
インターフェース型の使い方が...
-
System.Collections.Generic.Li...
-
C# 継承の問題で programに示さ...
おすすめ情報