継承は、インヘリタンスとも呼ばれます。既に用意されているオブジェクトを基に、機能などを追加して新たなオブジェクトを作ることができる機能です。
これから、Busクラスを作成してみましょう。バスは、人を乗せて運ぶことができますが、車と同じように進んだり、止まったりすることができます。つまり、Carクラスのような機能を持っています。「バスは車である」ということができます。このような関係を「is-a」の関係といいます(Bus is a Car)。
このような場合、BusクラスはCarクラスの機能等を引き継いで作成することができます。Carクラスを継承してBusクラスを作ることができます。このようにすることで、Busにしかない属性、機能を記述すればよくなります。つまり、CarクラスとBusクラスの差分を記述するわけです。
継承において、もとになるクラスをスーパークラスや基底クラスといい、それをもとに新しく作成するクラスをサブクラスや派生クラスといいます。
クラス継承の書式 |
---|
class サブクラス名 : スーパークラス名 { 各種定義… } |
継承の指定をした後、スーパークラスにはないフィールドやメソッドを追加や修正する記述をします。
○ プロジェクト
プロジェクトを作成して確認してみましょう。
プロジェクトの種類 | コンソール アプリケーション |
---|---|
プロジェクト名 | InheritanceTest |
○ 作成の準備
Busクラスを作成しましょう。「PropertyTest」をコピーしてプロジェクトを作成してください。
○ プログラム
Busクラスを追加して、次のように記述してください。
Bus.cs
○ クラス図
○ 解説
10行目でCarクラスを継承しています。これにより、Carクラスが持っているSpeedUpメソッド、SpeedDownメソッドが使えるようになります。
13行目のプロパティは売上金額を扱います。乗客が乗車するたびに加算されていきます。このプロパティはsetアクセサーにprivate修飾子がついているので、設定はクラス内部からしかできないようになっています。14行目のプロパティは現在の乗客数を扱います。今回は50人まで乗せられるようにプログラムで制御しています。このプロパティも設定はクラス内部からしかできないようになっています。
17~20行目ではコンストラクタを定義しています。このコンストラクタは引数なしで呼ばれると、オーバーロードしているガソリン量を受け取るコンストラクタを呼び出します。22~27行目では、ガソリン量を受け取るコンストラクタを定義しています。23行目はスーパークラスのコンストラクタを呼び出しています。「base」キーワードは、スーパークラスを表します。ここでのbaseキーワードはCarクラスを表します。
31~47行目は乗車するメソッドです。このメソッドは運賃を受け取り乗車処理をします。その際、バスが走っていたり、乗客数が満員になっていたりすると乗車できないようにしています。いずれにも当てはまらない場合は、受け取った運賃を売上金額プロパティに加算し、乗客数プロパティを1人分増やします。
50~65行目は降車するメソッドです。バスが走っていたり、乗客がいない場合は降車できないようにしています。いずれにも当てはまらない場合は、乗客数プロパティを1人分減らします。
○ プログラム
Busクラスを利用するプログラムを作成しましょう。次のように変更してください。
Program.cs
○ 解説
23行目でBusオブジェクトを生成しています。BusオブジェクトはCarクラスを継承しているので今まで通り加速したり、減速したりできます。54行目では乗車メソッドを呼び出しています。戻り値がnullでない場合はエラーメッセージが返って来ているので、コンソールに表示しています。66行目では降車メソッドを呼び出しています。このメソッドは乗車メソッドと同様にエラーメッセージかnullが返ってくるのでそれに応じた処理をしています。
今回はCarクラスを基にBusクラスを作成しました。BusクラスはCarクラスを継承しているので、Carクラスのメンバを記述しなくても使用することができます。ただし、privateになっているメンバは、継承したクラスでも直接アクセスすることができません。「protected」にすれば、直接操作できます。「protected」は、継承関係であればアクセスできますが、外部クラスからはアクセスすることができません。
VC#では、サブクラスは1つのクラスから継承することができます。複数のクラスから継承させることはできません。(多重継承の禁止)
Busクラスのインスタンスを生成するときにBusクラスのコンストラクタを呼び出します。すると、初めにスーパークラスであるCarクラスのコンストラクタを呼び出します。サブクラスのコンストラクタでスーパークラスのコンストラクタの呼び出しが特に記述されていない場合、スーパークラスのデフォルトコンストラクタが呼び出されれます。もし、スーパークラスで引数を持つコンストラクタが定義されていると、デフォルトコンストラクタは仮定されないので、サブクラスでスーパークラスのコンストラクタの呼び出しを記述しなければなりません。