継承
1 派生クラス
継承とは、あるクラスを土台にして、別のクラスを作成するための方法です。元になるクラスを「基底クラス」あるいは「スーパークラス」と呼び、それを継承する新しいクラスを「派生クラス」あるいは「サブクラス」と呼びます。
一つのクラスは、任意の個数の「派生クラス」を持つことが出来ますが、逆に、「基底クラス」は、多くのクラスで一つしか持てません。これを単一継承と呼び、クラスは継承されることで枝葉を広げていく木構造を成しています。そして、遡っていけば根っ子となる一つの「基底クラス」に行きつきます。ただし、C++ は、複数の「基底クラス」を継承できます。これを多重継承と呼びます。
クラスの木構造の頂点、ルートとなるクラスが Object クラスです。「基底クラス」を明示しないクラスの場合、自動的にこのクラスから派生されたことになります。「基底クラス」を明示した場合でも、そのクラスも Object クラスの「派生クラス」か、または Object クラスを継承したクラスの「派生クラス」のいずれかなので、最終的にはあらゆるクラスが Object クラスを「基底クラス」に持つことに変わりはありません。
「派生クラス」は、「基底クラス」の一種だと言えます。「乗り物」を継承して「自動車」を作り、「自動車」を継承して「バス」を作るようなもので、「バス」は「自動車」の一種であり、更に「乗り物」の一種です。
「派生クラス」は、「基底クラス」のメソッドやフィールドを全て継承して使えます。クラスの継承とはあるクラス(「基底クラス」)の機能を他のクラス(「派生クラス」)からでも使用できるということです。オブジェクトの中には非常に似た機能を持つものが多数あります。すべてのオブジェクトが、ただ1つのクラスから生成できればいいですが、クラスを新たに作成し、そこからオブジェクトを生成したほうがよい場合が多くあります。例えば、「バス」や「トラック」のオブジェクトを「自動車」クラスから生成するよりは、「自動車」クラスを継承し作成した「バス」や「トラック」クラスから生成したほうが効率が良いというわけです。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に extends に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に : に続いて、継承修飾子 と 基底クラス名を記述します。
多重継承する場合は、, で区切って複数記述します。
継承修飾子には次の意味があります。
| public | 基底クラスで設定したアクセス修飾子の設定をそのまま引き継ぐ |
| protected | 基底クラスでpublicだったものを、protectedにして引き継ぐが、他はそのまま |
| private | 基底クラスのメンバを全てprivateで引き継ぐ |
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト変数 amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に : に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト変数 amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド Siren を呼び出します。Ambulance クラスの Siren メソッドが実行されます。
- メソッド Run を呼び出します。Ambulance 内にないので Car クラスの Run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に Inherits に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の Private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。Run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の Siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに Siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、Siren と Run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト変数 amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド Siren を呼び出します。Ambulance クラスの Siren メソッドが実行されます。
- メソッド Run を呼び出します。Ambulance 内にないので Car クラスの Run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に extends に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」のメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に次のように qw() の中に基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」のメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト $amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に < に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」のメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に ( ) で囲って、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」のメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に extends に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト $amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に extends に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に : に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に : に続いて、基底クラス名を記述します。
ただし、基底クラスになるには、基底クラスの定義に open が記述されている必要があります。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に extends に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に extends に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
Go には継承という概念がありません。既存のクラスから派生したクラスを作成したい場合は、既存のクラスを埋め込むことによって派生したクラスを作成します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」のメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド Siren を呼び出します。Ambulance クラスの Siren メソッドが実行されます。
- メソッド Run を呼び出します。Ambulance 内にないので Car クラスの Run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に : に続いて、基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
既存のクラスから派生したクラスを作成したい場合、クラス定義時に class に続くカッコ内に基底クラス名を記述します。
例えば「救急車」を考えて見ましょう。
「派生クラス」は、「基底クラス」の private でないメソッドやフィールドを全て継承して使えます。しかし、すべてを引き継いだだけで、「基底クラス」と何ら変わらないのならば、「派生クラス」を作る意味はありません。ですから、「派生クラス」では、「基底クラス」にない独自のメソッドを追加したり、「基底クラス」のメソッドの働きを変更したりします。つまり、「自動車」は、「種類」や「走る」といったような、自動車に共通する特性や機能を持ちますが、「救急車」は「自動車」の性質に、「サイレンを鳴らす」といったような、独自の性質を加えたものとなるのです。
「自動車」クラスを継承して「救急車」クラスを作成します。run メソッドは「自動車」クラスのものをそのまま利用します。しかし、そのままでは「自動車が走る。」となってしまうので、"自動車"という名前を持っている kind をコンストラクタで変更します。また、サイレンを鳴らしたいので、「救急車」クラスに独自の siren メソッドを作成してあげる必要があります。それでは Ambulance クラスとして作成してみましょう。
Ambulance クラスは、新たに siren というメソッドを持っています。それでは、この Ambulance クラスのインスタンスを生成し、siren と run メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス Ambulance を宣言します。
- 〈処理の流れ〉
- 派生クラス Ambulance のオブジェクト amb を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド siren を呼び出します。Ambulance クラスの siren メソッドが実行されます。
- メソッド run を呼び出します。Ambulance 内にないので Car クラスの run メソッドが実行されます。
実行結果です。
ピーポーピーポー 救急車が走る。
2 オーバーライド
オーバーライドとは、「基底クラス」で定義されたメソッドを「派生クラス」で再定義することを言います。「基底クラス」のメソッドを変更することはできませんが、「派生クラス」に特化した機能を付与する必要がある場合などに使用します。
これに対して、オーバーロードとは、同一クラス内で、メソッド名が同一で引数の型、数、並び順が異なるメソッドを複数定義することを言います。
オーバーライドを定義する際には以下の規定があります。
(ただし、データの型やアクセスレベルのない言語ではこのような規定はありません。)
- オーバーライドする側は、オーバーライドされる側と、戻り値の型、インスタンスメソッド名、引数型、引数の数や順序が同じでなければなりません。どれか一つでも異なる場合はオーバーライドとは見なされません。
- オーバーライドされる側のメソッドに指定されるアクセスレベルより厳しい制限を持つアクセスレベルをオーバーライドする側のメソッドに付与することはできません。例えばオーバーライドされる側のインスタンスメソッドに protected が指定されている場合、オーバーライドする側のインスタンスメソッドに private を指定することはできません。
java の場合は、さらに次の規定があります。
- オーバーライドされる側のインスタンスメソッドに final が指定されている場合、そのメソッドは「派生クラス」でオーバーライドできません。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
C++ の場合は、さらに次の規定があります。
- オーバーライドされる側のインスタンスメソッドに virtual が指定されていない場合、そのメソッドは「派生クラス」でオーバーライドできません。「基底クラス」のメソッドが呼び出されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
C# の場合は、さらに次の規定があります。
- オーバーライドされる側のメソッドには、virtual が指定されている必要があります。そして、オーバーライドする側には、override を記述する必要があります。
- オーバーライドされる側のインスタンスメソッドに abstract が指定されている場合、そのメソッドは「派生クラス」で必ずオーバーライドしなければなりません。逆に、sealed が指定されていたらオーバーライドできません。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という Work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした Work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、Run メソッドと Work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
VB の場合は、さらに次の規定があります。
- オーバーライドされる側のメソッドには、Overridable が指定されている必要があります。そして、オーバーライドする側には、Overrides を記述する必要があります。
- オーバーライドされる側のインスタンスメソッドに MustOverride が指定されている場合、そのメソッドは「派生クラス」で必ずオーバーライドしなければなりません。逆に、NotOverridable が指定されていたらオーバーライドできません。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という Work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした Work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、Run メソッドと Work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド Run を呼び出します。基底クラス FireEngine 内にないので基底クラス Car の Run が実行されます。
- メソッド Work を呼び出します。基底クラス Car の Work ではなく、クラス FireEngine 内の Work が実行されます。
Javascript は、データの型やアクセスレベルがありませんが、派生クラスでオーバーライドすることができます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
Perl は、データの型やアクセスレベルがありませんが、派生クラスでオーバーライドすることができます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 $fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
Ruby は、データの型やアクセスレベルがありませんが、派生クラスでオーバーライドすることができます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
Python は、データの型やアクセスレベルがありませんが、派生クラスでオーバーライドすることができます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 $fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
Scala の場合は、さらに次の規定があります。
- オーバーライドする側には、override を記述する必要があります。
- オーバーライドされる側のインスタンスメソッドに abstract が指定されている場合、そのメソッドは「派生クラス」で必ずオーバーライドしなければなりません。逆に、final が指定されていたらオーバーライドできません。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした Work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、Run メソッドと Work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド Run を呼び出します。クラス FireEngine 内にないので基底クラス Car の Run が実行されます。
- メソッド Work を呼び出します。基底クラス Car の Work ではなく、クラス FireEngine 内の Work が実行されます。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
Delphi の場合は、さらに次の規定があります。
- オーバーライドされる側のインスタンスメソッドに virtual が指定されていない場合、そのメソッドは「派生クラス」でオーバーライドできません。
- オーバーライドする側のインスタンスメソッドには override を指定します。
例えば「消防車」を考えて見ましょう。「自動車」クラスを継承して「消防車」クラスを作成します。work メソッドを呼び出しても何も表示されないので、独自の性質として「火事を消す」という work メソッドを作成してあげる必要があります。それでは FireEngine クラスとして作成してみましょう。
FireEngine クラスは、オーバーライドした work というメソッドを持っています。それでは、この FireEngine クラスのインスタンスを生成し、run メソッドと work メソッドを呼び出すクラスも作成してみましょう。
- 〈宣言/定義〉
- Car を基底クラスに持つ派生クラス FireEngine を宣言します。
- 〈処理の流れ〉
- 派生クラス FireEngine のオブジェクト変数 fir を宣言、生成します。
- オブジェクト生成時、コンストラクタが実行されます。そこから基底クラスのコンストラクタを呼び出します。
- メソッド run を呼び出します。クラス FireEngine 内にないので基底クラス Car の run が実行されます。
- メソッド work を呼び出します。基底クラス Car の work ではなく、クラス FireEngine 内の work が実行されます。
実行結果です。
消防車が走る。 火事を消す。