dポイントプレゼントキャンペーン実施中!

C++、VB.net、Java、Delphiなど色々なオブジェクト指向言語がありますが、
以下のようなとき、「子クラスのrunメソッド」を実行したとき、
(1)「親」と表示されてから「子」と表示される。
(2)「子」とだけ表示される。
のそれぞれどちらの仕様なのでしょうか?

親クラス
  runメソッド
    コンソールに「親」と表示

子クラス
  runメソッド
    コンソールに「子」と表示

※私は、
子クラス側で、わざわざ、super.run と書かずとも、
勝手に「(1)「親」と表示されてから「子」と表示される。」になる言語が多いと認識していたのですが、
誤った認識でしょうか?
(C++は、明示的に親の同名メソッドをコールしなければ、処理が実行されないと認識していますがC++の仕様は少数派でしょうか?多数派でしょうか?)

A 回答 (7件)

派生クラスで基底クラスの関数を上書きした場合は、派生クラスで定義された動作になります。



従って、答えは(2)になります。

基底クラスの動作を残しつつ派生クラスの処理を追加したい場合は、
普通はテンプレートメソッドを適用して基底クラスを設計します。

ただし、仮想になっていないメソッドを上書きするとポインタまたは参照の型によって動作が変わります。

いずれにせよ、明示的に書かない限り(1)の動作はしません。

この回答への補足

C++では、同名メソッドを書くとオーバーライドになるんですね。
驚き&意外です。

子側の関数で、
superclass::run を書く方法以外で、
メソッドの継承はできないのでしょうか??

補足日時:2013/06/29 21:38
    • good
    • 0
この回答へのお礼

ありがとうございます。
(#6の方にてお礼申し上げます)

お礼日時:2013/07/02 00:12

>私が触ってきた言語では、通常、


>何も書かなくても親の処理が実行され、
>子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。

それが何という言語なのか、興味ありますね。その言語では、下記のような場合にどうやって記述するのでしょう。
[A]親クラスのrunメソッドと全く違うことを子クラスのrunメソッドでやりたい(コンソールに「親」と表示したくない)場合
[B]コンソールに「子」と表示してからコンソールに「親」と表示したい場合

super.run()を明示的に書く言語(C++とかJava)では[B]は明らかですし、[A]もsuper.run()を書かないだけで実現できます。
    • good
    • 0
この回答へのお礼

子側のクラスで「このメソッドはオーバーライドします」と書くと、継承上書きできる仕様でした。

デフォルトが、処理の継承(※処理の追加)で、明示的に継承上書きと書くと、継承上書きになったと記憶しています。

どの言語だったかは覚えていないのですが、
古めのバージョンのpowerbuilderだったような気がします。
でも、皆さんから突っこまれて、なんか記憶に自信がなくなってきました。。

お礼日時:2013/07/02 00:18

#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 …
    • good
    • 0
この回答へのお礼

ありがとうございます。

テンプレートメソッドは、以下のようなときだけ使っていました。

ordered_process {
step1;
step2;
}

step1{
}

step2{
}

/*************************/

例を出して頂いて気づきましたが、
確かに、
step1は親のメソッドにしか実装せず、
逆にstep2を子だけにしか実装しないようにすれば、
(ordered_processをパブリック、step1をprivateにして隠蔽、step2をprotected)

「通常、何も書かなくても親の処理が実行される」
はできそうですね!

ありがとうございます。

お礼日時:2013/07/02 00:07

> 私が触ってきた言語では、通常、何も書かなくても親の処理が実行され、


> 子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。
その「差分だけ追記」というのが、ちょっと気になります。
あるクラスが100個のメソッドを持っていて、その殆どを使いまわしつつ幾つか機能を追加したクラスを新たに作りたい、というようなケースで、
「継承」の概念を用いて親のメソッドをほとんどそっくり貰ってきて、足りない分は子に追記する、というのが、オブジェクト指向で「差分を追記」と言った場合の意味合いに通常なります。
行単位・文単位ではなく、メソッド単位の追加なんです。

そこが不思議でならないのですが・・・


>#4
> C++にしろ、smalltalkにしろ、自分がぱっと思い当たるもので、上記挙動をする言語はないような。
私も同感です。ちょっと聞いたことがない。Common Lispなんかの例外中の例外を除けば。
    • good
    • 0
この回答へのお礼

う~ん、#4さんも、#5さんも仰っているということは、
私の勘違いだったのかもしれません。

ありがとうございます。
(時間があれば、色んな言語で再確認してみたいと思います。)

お礼日時:2013/07/02 00:09

回答じゃないけど、



> 私が触ってきた言語では、通常、何も書かなくても親の処理が実行され、
> 子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。

C++にしろ、smalltalkにしろ、自分がぱっと思い当たるもので、上記挙動をする言語はないような。

具体的にどの言語が、そのような挙動を示すか、補足したほうが回答が得られやすいと思います。
    • good
    • 0
この回答へのお礼

ありがとうございます。

どの言語でそうだったか、書ければ書きたかったのですがうろ覚えで書けませんでした...

(vb.netか、powerbuilderか、javaか、delphiのどれかだったとは思うのですが。)

お礼日時:2013/07/01 23:11

#1です。



> 継承のためには、以下のように書くケースが多いということでしょうか?
あなたの言う「継承」の意味がはっきりしないのですが、子クラスが存在する理由は「親クラスとは微妙に違うことをやりたい」という点にあるので、一般に、親クラスの同名メソッドが勝手に実行されては困ります。
例えば、次の例を考えてみてください。

親クラス:車
 accelメソッド
  自身の速度を5[m/s]上昇させる

子クラス:トヨタの何とかっていう車、親クラスは「車」
 accelメソッド
  自身の速度を10[m/s]上昇させる

この場合、子クラスのaccelメソッドを呼び出した時に自動的に親クラスが呼び出されてしまうと、「そこ書いてあること」と「実際に起こること」との間に差が生まれてしまい、可読性を損なう等の問題が発生します。
その為、「わざわざ親クラスを呼び出したい」という場合には、「わざわざそう指定してやる必要がある」というのが、多くの言語でよく採られている方式です。

又、子クラスに「自身の親クラスはhoge型」だと明示するのは、親子関係を生じさせる時点で既にやっていることのように思えます。色々と無駄です。
    • good
    • 0
この回答へのお礼

ありがとうございます。

「親クラスとは微妙に違うことをやりたい」で目的は合っていますが、
私が触ってきた言語では、通常、
何も書かなくても親の処理が実行され、
子側では、差分だけ、同名メソッドに追記するだけでよいということが多かった気がします。

なので、今のところ、C++では、
子側の関数で、
superclass::run を書く方法で考えています。

私は、

親クラス:車
 speedプロパティ
  x

 accelメソッド
  自身の速度をx[m/s]上昇させる

子クラス:トヨタの何とかっていう車、親クラスは「車」
 accelメソッド
  (※何も書かなくても、自身の速度をx[m/s]上昇させる)
  速度を上昇した後に行う処理を、追記しておく。

という記述方式の言語が多かったです。
(superclass::accelを書く必要がなかったです)

お礼日時:2013/06/29 21:48

一言で言うと、言語によって違う、ということになります。


又、一般のメソッドと一部の(コンストラクタのような)メソッドとでも違いが生まれます。

ただし、この場合では、「親クラスのrunメソッドが子クラスによってオーバーライドされている」という扱いになるでしょうから、理屈の上では、親クラスのrunメソッドは「呼ばれない」方が正しい実装になるかと思われます。

この回答への補足

ありがとうございます。
継承のためには、以下のように書くケースが多いということでしょうか?

親クラス
  runメソッド
    コンソールに「親」と表示

子クラス : 親クラスはhoge型
  runメソッド : 親クラスはhoge型
    コンソールに「子」と表示

補足日時:2013/06/29 14:18
    • good
    • 0
この回答へのお礼

ありがとうございます。
上の方のご回答でお礼申し上げます。

お礼日時:2013/06/29 21:58

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!