アルゴリズムとプログラミング

アルゴリズムとプログラミング
(Algorithms and Programming)
第11回:継承の実装
•継承の実装: extends キーワード
コンストラクタ
•継承とメソッドのオーバーライド,可視性
•抽象クラス (abstractキーワード)
講義資料等: http://www.pe.titech.ac.jp/~watanabe/lecture/ap/index-j.html
スーパークラス
継承の実装
Vehicle(乗り物)
- speed: double
# changeSpeed(s:double)
# getSpeed(): double
サブクラス
Plane
- altitude: double
# takeOff ()
# land ()
サブクラスは、スーパークラス
の全てのフィールドとメソッドを
含んでいる。
(実際にアクセスできるかは、
アクセス修飾子に従う)
継承の実装:extendsキーワード
スーパークラス
Vehicle(乗り物)
- speed: double
# changeSpeed(s:double)
# getSpeed(): double
サブクラス
Plane
- altitude: double
# takeOff ()
# land ()
class Plane extends Vehicle {
private double altitude;
protected void takeOff() {
処理(スーパークラスのメソッドも呼べる);
}
protected void land() {
処理;
}
}
スーパークラスへのアクセス
スーパークラス
Vehicle(乗り物)
- speed: double
# changeSpeed(s:double)
# getSpeed(): double
サブクラス
Plane
- altitude: double
# takeOff ()
# land ()
public static void main(略) {
Plane o = new Plane();
o.changeSpeed(0.0);
for(int i=0;i<=300;i+=50){
o.changeSpeed(i);
o.takeOff();
}
System.out.println("離陸!");
}
}
全てのクラスのスーパークラス
Objectクラス
extendsキーワードが
無い全てのクラスは、自
動的にObjectクラスの
サブクラスとなる。従っ
て、全てのクラスは
Objectクラスのフィー
ルドとメソッドを暗黙的に
継承している。
Objectクラス
Vehicle(乗り物)
- speed: double
# changeSpeed(s:double)
# getSpeed(): double
Plane
- altitude: double
# takeOff ()
# land ()
継承とコンストラクタ
サブクラスのコンストラクタを呼び出すと..
1. まずスーパクラスのコンストラクタが実行される
(何も指定しなければデフォルトコンストラクタが呼ばれる.引数は無し)
2. 次にサブクラスのコンストラクタが実行される
サブクラスのコンストラクタ(例)
SampleAP0901.java
class
int
X()
x
}
}
class
int
Y()
y
}
}
X {
x;
{
= 100;
Y extends X {
y;
ここにsuper();が省略
{
= 200;
されていると考える
サンプルプログラム(続き)
SampleAP0901.java続き
class SampleAP0901 {
public static void main(String[] args) {
Y o = new Y();
System.out.println("x= " + o.x );
System.out.println("y= " + o.y );
}
}
実行結果
x= 100
y= 200
親のコンストラクタを指定する場合
Superキーワード
SampleAP0902.java
class X {
int x;
X(int a) {
x = a;
}
}
class Y extends X {
int y;
Y(int a, int b) {
super(a);
y = b;
}
}
(thisキーワードとの併用は不可)
コンストラクタでsuperを使うときは
最初の行でしか使えない!
SampleAP0902.java続き
class SampleAP0902 {
public static void main(String[] args) {
Y o = new Y( 1, 2 );
System.out.println("x= " + o.x );
System.out.println("y= " + o.y );
}
}
実行結果
x= 1
y= 2
暗黙の親コンストラクタ呼び出し
SampleAP0901.java(再)
class
int
X()
x
}
}
class
int
Y()
y
}
}
X {
x;
{
= 100;
Y extends X {
y;
ここにsuper();が省略
{
= 200;
されていると考える
継承を禁止するfinalキーワード
final class X {
int x;
サブクラスの宣言を禁止!
}
class Y extends X {
int y;
}
コンパイルエラー!
final宣言したクラスは、extendsで
サブクラスを作ることが禁止される
メソッドのオーバーライド
オーバーライド(override)
親クラスと子クラスのそれぞれに、
メソッド名、引数、戻り値が全て同一で
内容が異なるメソッドを定義すること
既出
オーバーロード (overload)
混同注
意!
ひとつのクラス内に、メソッド名が同じ
で、引数の型及び数が異なるメソッドを
定義すること
オーバーライドの目的
Vehicle(エンジン付き乗り物)
- speed: double
# getSpeed(): double
# startEngine ()
Plane
- altitude: double
# takeOff ()
# startEngine ()
もともと、サブクラスにはスー
パークラスのフィールドとメ
ソッドが全て自動的に引き継
がれている。
しかし、引き継がれているメ
ソッドの処理内容を、サブク
ラスで再定義(変更)したい場
合がある 。
オーバーライドの必要性
オーバーライドと可視性
子クラスでオーバーライドするメソッドの可視性
は、親クラスのメソッドの可視性により制限される
オーバーライドされる
スーパークラスのメソッド
に指定されている修飾子
オーバーライドするサブクラスのメソッド
public
public指定が必要
protected
protectedかpublicが必要
private
アクセス不可につき、オーバーライド不可
無指定
private指定は不可
親クラスでprotectedが指定されているメソッドを子クラスでオーバーライドするにはprotectedかpublic指定が必要
親・子クラスにおける
オブジェクト参照型変数の互換性
Javaのきまり:
型の違いに厳しいJavaですが..
•子クラスのインスタンスを指すオブジェ
クト参照型変数を、親クラスの参照変数
に代入することができる。
•代入後も、インスタンスの出身が子クラ
スであることを忘れずに記憶しておく仕
組みになっている。
1つのオブジェクトが、あたかも複数の型を持
つかのように見せることができる。
オブジェクト指向3原則:ポリモーフィズム
(メソッドのオーバーライドと参照型変数の
互換性によって実現される)
乗り物
飛行機
ジェット機
ジェット機クラスのインスタン
スを、乗り物オブジェクトとして
扱うことができる。
自動車
プロペラ機
ジェット機は飛行機でも
あり、乗り物でもある
ジェット機クラスのインスタン
スに対する操作を、乗り物に
対する操作として記述できる
このような記述の仕方に
どんなメリットがあるの?
乗り物
#動力を始動する()
飛行機
自動車
#動力を始動する()
ジェット機
#動力を始動する()
#動力を始動する()
プロペラ機
#動力を始動する()
操作名は同じだ
が、実際の操作
内容はそれぞれ
異なる
メソッドのオーバーライド
ジェット機クラスのインスタンスを生成する
:ジェット機
new ジェット機();
このインスタンスを乗り物オブジェクトと見なす
(乗り物オブジェクト変数 v1 に格納する)
乗り物 v1 = new ジェット機();
乗り物クラス
ジェット機クラスのインスタンスへの参照
動力を始動する()メッセージを送る
v1.動力を始動する()
乗り物オブジェクトの操作が呼び出
されるように記述されているが、自動
的にジェット機オブジェクトに対する
操作が呼び出される
この記法は、ジェット機に限ら
ず、プロペラ機にも自動車にも、
将来的に追加される乗り物に
もそのまま変更なく使える。
上位概念(スーパークラス)オブジェクトに対する操作と
して記述しておくと、サブクラスの細かい修正や追加な
どに対して強いプログラムになる(保守性が高い)
ジェット機クラスのインスタンスを生成する
:ジェット機
new ジェット機();
このインスタンスをジェット機オブジェクト変数 j1 に格納する
ジェット機 j1 = new ジェット機();
ジェット機クラス
ジェット機クラスのインスタンスへの参照
動力を始動する()メッセージを送る
j1.動力を始動する()
この記法では、プロペラ機や自動車に変更したり、さらに
は将来的に追加される乗り物に対しては、そのままでは
使えない。プログラムの記述を変更する必要がある!
ポリモーフィズムの意味と効果
ポリモーフィズム(polymorphism)の意味:
1つのオブジェクトが複数の型を持つ ← 継承により実現
ポリモーフィズムの活用の仕方:
上位概念(スーパークラス)への操作としてプログラ
ムを記述する
その効果:
サブクラスの細かい修正や追加などに対して強い
(保守性が高い)プログラムになる
オブジェクト指向プログラミングの有効性!
参照型変数への代入 (例)
SampleAP1001.java
class X { // スーパー(親)クラス
int x;
}
class Y extends X { // サブ(子)クラス
int y;
}
class SampleAP1001 {
public static void main(String[] args){
X o = new Y();//サブクラスYのインスタンスを親クラスX
}
//の参照型変数へ代入できる!
}
メソッドのオーバーライド(例)
SampleAP1002.java
class Shape { //2次元図形の面積を表現するクラス
double a; //一般に、面積を計算するには、縦×横や底辺×高さ/2など、
double b; //2つの辺の長さを与える必要があると考え、変数を2つ用意する
Shape(double x, double y) {
a = x;
b = y;
}
double getArea() { //ここでは具体的な定義を与えないことにする。
return 0.0;
//具体的な定義はサブクラスで与える。
}
}
SampleAP1002.java続き
class Triangle extends Shape { //三角形
Triangle(double x, double y);
super(x,y); // x,yとしては底辺と高さを与える
}
double getArea() {
オーバーライド
return ( a * b / 2 );
}
}
class Rectangle extends Shape { //四角形
Rectangle (double x, double y){
super(x,y); //x,yとしては各辺の長さを与える
}
double getArea() {
オーバーライド
return ( a * b );
}
}
SampleAP1002.java続き
class SampleAP1002 {
public static void main(String[] args) {
Shape o1 = new Shape( 10.0, 10.0 );
Shape o2 = new Triangle( 10.0, 10.0 );
Shape o3 = new Rectangle( 10.0, 10.0 );
System.out.println("o1の面積は" +
o1.getArea() );
System.out.println("o2の面積は" +
o2.getArea() );
System.out.println("o3の面積は" +
o3.getArea() );
}
}
実行結果
o1の面積は0.0
o2の面積は50.0
o3の面積は100.0
引数に与えた数値はo1~o2まで
全て同じだが、それぞれオーバー
ライドされたgetArea()メソッドが、
異なる処理を実行している。
抽象クラス: 抽象メソッドを持つためオブジェ
クト生成できないクラス
乗り物
-スピード
#スピードを変える()
#スピードを表示する()
飛行機
-高度
#離陸する()
#着陸する()
#高度を表示する()
クラス名をイタリックにすると
抽象クラス
乗り物クラスのインスタンスは
存在しないことが保証される
飛行機クラスでは、依然として
スピードを表示する()操作は必須
であり、乗り物クラスは使われる。
抽象クラスの実装
親クラスではメソッド名だけ定義して、子ク
ラスにおいて、オーバーライドにより具体的
な処理内容を記述する
抽象メソッド: abstractキーワード
具体的な処理内容が与えられていな
いため、インスタンスの作成は不可
抽象クラスの使用例
SampleAP1003.java
abstract class Shape { //抽象クラス
double a;
double b;
Shape(double x, double y) {
a = x;
b = y;
}
//抽象メソッドとして定義(この方が自然)
abstract double getArea();
}
•抽象メソッドが1つでもあるとそのクラスは抽象クラス
→サブクラスで具体的な処理内容を与えて使用する
•抽象クラスだからといって、全てが抽象クラスである必要は無い
SampleAP1003.java続き
この部分はSampleAP1002.javaと同じ
class Triangle extends Shape { //三角形
Triangle(double x, double y);
super(x,y); // x,yとしては底辺と高さを与える
}
double getArea() {
return ( a * b / 2 );
}
}
class Rectangle extends Shape { //四角形
Rectangle (double x, double y){
super(x,y); //x,yとしては各辺の長さを与える
}
double getArea() {
return ( a * b );
}
}
SampleAP1003.java続き
class SampleAP1003 {
public static void main(String[] args) {
Shape o2 = new Triangle( 10.0, 10.0 );
Shape o3 = new Rectangle( 10.0, 10.0 );
System.out.println("o2の面積は" +
o2.getArea() );
System.out.println("o3の面積は" +
o3.getArea() );
}
}
抽象クラスのインスタンス化を削除
まとめ1
•継承の実装: extends キーワード
•継承とコンストラクタ: superキーワード
•継承の禁止: finalキーワード
まとめ2
•継承とメソッドのオーバーライド
•抽象メソッド、抽象クラス
より保守性の高いプログラムの実現
世の中で既に作成され公開されている各種のJavaクラ
スライブラリはこのような考え方で作成されている。適当
なクラスを継承してカスタマイズすることにより、極めて
簡単に自分独自の問題を解決することができる。