本日の課題

Download Report

Transcript 本日の課題

オブジェクト指向プログラミング
12回目:継承(ポリモーフィズム),インタフェース,
パッケージ
情報メディア学科
濱本和彦
本日の内容
ポリモーフィズム
インタフェース
パッケージ
メソッドの修飾子(復習)
abstract


このクラスでは実装しない空のメソッド
クラス自体もabstractでなければなりません
final

オーバーライドできないメソッド
private

同じクラス内のコードからしか呼び出されないメソッド
protected

サブクラスまたは同じパッケージ内のコードからしかアクセスできないメ
ソッド
public

ほかのクラスからアクセスできるメソッド
static

インスタンスメソッドではないメソッド
※ public, protected, private は,他の修飾子と同時に指定できません。
メソッドの修飾子(復習)
Example64.java
クラスもabstract
となります。
class Example64{
abstract class Vehicle{
public static void main(String args[]){
abstract int numWheels();
Car car = new Car();
抽象メソッドの宣言
}
Truck track = new Truck();
class Car extends Vehicle{ { }は付けません。
System.out.println(car.numWheels());
int numWheels(){
System.out.println(truck.numWheels());
return 4;
} 「乗り物」クラスを用意し,その中にタイヤの数を
Vehicleクラスを継承した
}
Carクラス内で実装します。 }
確認するメソッドを用意します。これらは「抽象ク
}
ラス」「抽象メソッド」であり実体はありません。
class Truck extends Vehicle{
「乗り物」クラスを継承した「車」クラス内で,タイヤ
int numWheels(){
の数を4つと指定(=メソッドを実装)します。同様
return 6;
に「トラック」クラスでタイヤの数を6つと指定します。
Vehicleクラスを継承した
}
Trackクラス内で実装します。
「車」「トラック」それぞれのオブジェクトがもつメソッド
}
を実行してタイヤの数を出力します。
ポリモーフィズム(復習)
「ポリモーフィズム」とは,メソッドを呼び出す側の処理を
一つにまとめてしまう仕組みです。
呼び出される側が増えても,それぞれについての「呼び
出し方」を覚える必要がありません。
Example64.javaでは,車のタイヤの数を知る時は,車オ
ブジェクトに対してnumWheelメソッドを呼び出し,トラック
のタイヤの数を知る時は,トラックオブジェクトに対して
numWheelを呼び出し,実行しました。
numWheelだけ知っていれば,乗り物の種類(=呼び出
される側)が増えてもOK,という仕組みになっています。
Example65.javaは,これを応用したものです。
ポリモーフィズム(復習)
Example65.java
class Owner{
void getNumWheels(Vehicle vehicle){
System.out.println(vehicle.numWheels());
}
}
抽象クラスVehicle,抽象メソッドnumWheels()
を対象とした,呼び出し側のクラスOwnerを作成。
メソッドgetNumWheels( )は,抽象クラスVehicle
を継承したクラスのオブジェクトを引数とすること
ができる。
class Example65{
そのオブジェクトが実装している抽象メソッド
public static void main(String args[]){
numWheels( )を実行する。
Owner owner = new Owner();
Car car = new Car();
呼び出し側が,Vehicleクラスを継承したCarクラスのオブジェ
Truck truck = new Truck();
クトcarを引数としてメソッドgetNumWheels( )を呼び出すと,
owner.getNumWheels(car);
carが実装するメソッドnumWheels( )が実行される。
owner.getNumWheels(truck);
呼び出し側が,引数をTruckクラスのオブジェクトtruckに変えて
}
メソッドgetNumWheels( )を呼び出すと,自動的にtruckが実装
}
するメソッドnumWheels( )が実行される。
呼び出す側は,getNumWheelsだけ意識して,そこに抽象クラスを継承してインスタンス化されたオブジェクトを与えれば良い。
演習
Example65.javaに,Vehicleクラスを継承
するBikeクラスを作成し,numWheels()メ
ソッドを実装して下さい。ownerオブジェクト
からそのメソッドを呼び出して下さい。
3回目の授業で「ポリモーフィズム」を説明
するためにtest_pm.cppというC++のプロ
グラムを利用しました。これをJavaで書き
直してみましょう(Problem12.java)。
インタフェース
インタフェースとは,クラスの「型」「機能」「役割」を表現したも
のです。
定数とメソッドの宣言からなります。メソッドは宣言のみで,実
際の処理は実装されません。
あるインタフェースを取り付けた(実装した)クラスは,「同じ仲
間」のクラスとなります。
クラスは,複数のインタフェースを実装することが出来ます。
インタフェースを実装したクラスでは,インタフェースで宣言さ
れているメソッドを必ず実装(実際の処理を定義)しなければ
なりません。
ポリモーフィズムを実現する一つの手段です。
インタフェース
Example66.java
Example66.javaでインタフェースの働きを確認してくださ
い。
ここで作られたCircleクラスとRectangleクラスは,両者と
もShape2Dインタフェースを実装(implements)していま
す。
つまり,「CircleクラスとRectangleクラスは,両方とも
Shape2Dインタフェースの仲間である」ということを定義
している訳です。
CircleクラスとRectangleクラスでは,Shape2Dインタフェ
ースのgetAreaメソッドが実装され,それぞれ円の面積を
計算するメソッド,四角形の面積を計算するメソッドとして
働きます。
つまり,ポリモーフィズムが実現されています。
インタフェースの参照
インタフェースの名前を「変数の型」として
利用できます。
この時,この変数は,「インタフェースを実
装したオブジェクトへの参照」となります。
よって,この変数にインタフェースを実装し
ていないオブジェクトを代入しようとすると
コンパイルエラーとなります。
Example67.javaで確認しましょう。
インタフェースの参照
Example67.java
InterfaceA a;
InterfaceAインタフェース型の変数aを宣言
a = new Class1();
a.display("String 1");
aにClass1クラスのオブジェクトへの参照を代入
Class1クラスのdisplayメソッドが実行
Class1: String 1
a = new Class2();
a.display("String 2");
aにClass2クラスのオブジェクトへの参照を代入
Class2クラスのdisplayメソッドが実行
Class2: String 2
a = new Class3();
a.display("String 3");
aにClass3クラスのオブジェクトへの参照を代入
Class3クラスのdisplayメソッドが実行
Class3: String 3
継承の場合のこれと同じですね。
abstractの使い方
Example61.java
class Example61{
abstract class Shape{
void display() { メソッドの中身(実体)は public static void main(String args[]) {
Shape s = new Circle();
}
ここでは宣言しません
s.display();
}
s = new Rectangle();
class Circle extends Shape{
s.display();
void display() {
}
System.out.println("Circle");
Shapeクラスの参照sは,それを継承し
}
}
たクラスのオブジェクトとして実体化
}
(インスタンス化)されます。
継承クラスごとに機能が異なるメソッド
class Rectangle extends Shape{
が実装されます
void display() {
System.out.println("Rectangle");
Shapeクラスを継承したクラスの中で
}
メソッドの実体を宣言します
}
インタフェースの参照
Example68.java
Example68.javaはコンパイルするとエラ
ーが出ます。
まずはどのようなエラーが出るか予想して
ください。その後,実際にコンパイルして予
想を確認してください。
このエラーを回避できるようにプログラムを
修正してください。
インタフェースの継承
クラスと同様,インタフェースもextendsキーワードを利用
して継承することが出来ます。
クラスと異なり,インタフェースは,複数のインタフェース(
スーパーインタフェース)を直接拡張できます。
複数のスーパーインタフェース内で同じ名前の変数が宣
言されているとエラーになります。
複数のスーパーインタフェース内で同じ構文のメソッドが
宣言される場合は,戻り値の型は同一でなければなりま
せん。
修飾子 interface サブインタフェース extends スーパーインタフェース1, スーパーインタフェース2{
// インタフェースの本体
}
クラスの継承と
インタフェースの継承
同名の変数は宣言できない
メソッドの返り値の型は同じとする
変数aは定数として宣言
メソッドは型のみの宣言
スーパークラス
int a;
double f(int x){
・・・
}
extends
スーパーインタフェース1
int a=100;
double f(int x);
extends
直接継承できる
クラスは1つだけ
サブクラス1
double f(int x)
int f(int x)
メソッドfがオーバーライドされる
返り値の型は同じとする
サブクラス2
double a;
double f(int x, int y)
サブクラスの変数aが優先
メソッドfがオーバーロードされる
クラスの継承
スーパーインタフェース2
double a=6.8;
double f(int x, int y);
int f(int x);
extends
インタフェース
int g(int z);
一度に複数の
インタフェースを
継承できる
implements
クラスでは,全て
クラス
のインタフェース
double f(int x){ ・・}
のメソッドを全て
double f(int x, int y){・・} 実装しなければ
ならない
int g(int z){・・}
インタフェースの継承
インタフェースの継承
Example69.java
Example69.javaでインタフェースの継承
の様子を確認しましょう。
パッケージ
「パッケージ」とは,「クラスやインタフェースの集まり」のこ
とです。
1つのソースファイルに含まれるクラスやインタフェースを1
つにまとめることが出来ます。
つまり,複数のファイル(クラスやインタフェース)をまとめ
て一つのパッケージとし,そのパッケージを利用してプログ
ラムを書く,ということができます。
パッケージに含まれるファイルは,パッケージ名と同じフォ
ルダの中になければなりません。階層構造も可能です。
あるファイルを,あるパッケージに含む場合は,最初の行
に次のように記述します。
package パッケージ名;
パッケージ
パッケージpの作成と利用
フォルダ名とパッケージ名は同じ
フォルダp
A.java
B.java
Example70.java
package p;
package p;
package p;
class A{
void a1( ){
System.out.println("a1");
}
}
class B{
void b1( ){
System.out.println(“b1");
}
}
class Example70{
public static void main(・・・・){
A a = new A( ); a.a1( );
B b = new B( ); b.b1( );
}
}
パッケージに含まれるファイルは
そのフォルダの下に配置する
同一パッケージ内であれば,
他のファイルで宣言された
クラスの利用も可能
パッケージ:演習
パッケージを指定しない場合は,既定のパッケージに割
り当てられます。
Visual Studioの場合,プロジェクト名がパッケージ名に
相当します。

プロジェクトを作成したとき,その名前のフォルダが自動的に作ら
れます。
pという名前のプロジェクトを作成し,そこに「追加」「既存
の項目」からA.java, B.java, C.java, Example70.javaを
選択,追加してください。
pという名前のフォルダが作成され,4つのファイルが追
加されていることを確認してください。
Example70.javaをビルド・実行して,A.java, B.java,
C.javaで宣言されているクラスからオブジェクトを作成,
実行できることを確認してください。