オブジェクト指向 プログラミング演習 第 4 回継承 オーバーライド ポリモルフィズム
今日のお題 継承 オーバーライド ポリモルフィズム
継承 (inherit) あるクラス c のサブクラス s を定義する : このとき s は c を継承していると言う 何かの下位概念を表すクラスは その上位概念を表すクラスの属性や機能を ( 基本的には ) 使える
継承の例 大学生 長崎県立大学の学生 大学生を継承する概念 シーボルト校の学生 長崎県立大学の学生を継承する概念 大学生も継承している
多重継承 あるクラスが複数のクラスのサブクラスとなることを 多重継承と呼ぶ 複数のクラスの性質を兼ね備えたクラスを考えると ものごとを整理しやすいこともある 例 ) 水陸両用車の機能を考えるときは 車と船の両方のサブクラスと捉える ただし Java は厳密な意味での多重継承をサポートしていない
Java のインタフェース クラスのように型として使える そのインタフェースに合致する機能を持ったモノの種類を表す メソッドの型だけ宣言する メソッドの中身は このインタフェースを実装するクラスの中で定義する メソッドはクラスが持つ機能を表すので インタフェースは その型 ( 機能の概要 ) だけを表している インタフェースの実装は 継承を一部だけ表現する
Java における継承の表現 extends クラス名 クラスの宣言時にクラス名の後ろにつけて 別のクラスのサブクラスであることを示す クラスを宣言するときに extends で継承できるクラスは一つだけ implements インタフェース名,... クラスの宣言時にクラス名の後ろにつけて インタフェースを実装しているクラスであることを宣言する クラスを宣言するときに implements で複数のインタフェースを ( カンマで区切って ) 並べることができる
継承の実例 java.awt.canvas は画像を表示するための画面を表すクラス Canvas そのものは 何も表示しない 表示のための機能を持っている : 画像の表示が必要なときに Canvas クラスの paint メソッドが呼ばれる仕組みが用意されている ただし Canvas クラスの paint メソッドは 何もしない Canvas のサブクラスとして 特定のゲームのための画像を表示するための画面を表すクラスを考える : paint メソッドを ( 上書きで ) 定義して 絵を描く スーパークラスで定義されているメソッドを上書き定義することを オーバーライドと呼ぶ
プログラム例 import java.awt.*; public class Oop4 { } Frame f; Oop4() { } MyCanvas c = new MyCanvas(); f = new Frame("Oop4"); f.add(c); f.pack(); f.setvisible(true); public static void main(string args[]) { new Oop4(); } class MyCanvas extends Canvas { } MyCanvas() { setsize(600,600); } public void paint(graphics gc) { } int i; gc.setcolor(new Color(0,160,0)); gc.fillrect(0,0,600,600); gc.setcolor(new Color(0,0,0)); for(i=0 ; i<4 ; i++) { } gc.drawline(30+i*180,30,30+i*180,570); gc.drawline(30,30+i*180,570,30+i*180); MyCanvas は Canvas のサブクラス ここではコンストラクタと paint メソッドをオーバーライドしている このコンストラクタと paint メソッド以外は Canvas と同じ
継承と 型の包含関係 あるクラスのインスタンスを そのクラスのスーパークラス型の仮引数で受け取ることができる スーパークラス型の変数に代入することも 同様にできる 例 ) MyCanvas クラスのインスタンスは Canvas クラスのインスタンスでもあるので Canvas を受け取るメソッドに渡すことができる 先のプログラム例 7 行目 : f.add(c); Frame の add は Canvas を受け取れる MyCanvas のインスタンス c を渡すことができる add は Container クラスで定義され Component を受け取る Frame は Container のサブクラスであり Canvas は Component のサブクラスである
ポリモルフィズム 同じ名前で異なる型の引数を受け取るメソッドを複数定義できる ( 名前が同じでも 引数の型が違えば 違うメソッドとして扱われる ) i.e. 呼び出すときの引数によって 異なるメソッドを呼び出せる 使い方 : 本質的には同じ機能だが 引数に複数の表現の仕方がある場合 引数のいくつかを省略できる場合
Java のいろいろについて ちょっと説明 以下 授業内容の先取りになってしまう項目もありますが 要素技術の紹介に必要なので 簡単に説明しておきます : this 文字列との加算 tostring メソッドのオーバーライド 配列の宣言 例外 ( 第 8 回の予定 ) null マルチスレッド ( 第 9 回の予定 )
this あるメソッドやコンストラクタの中で そのオブジェクト自身を指すために this というキーワードを使う この id はインスタンスのフィールド 例 ) class Card { int id; Card(int id) { this.id = id; } } この id はコンストラクタの引数
文字列との加算 文字列同士の加算 (+) は 文字列の連結を表す 例 )System.out.println("Hello"+" "+"World"); どのオブジェクトも文字列と加算すると 文字列になる例 ) int x = 10; String s = ""+x; この s は "10" という文字列になる
tostring メソッドのオーバーライド System.out.println でオブジェクトを表示するとき そのオブジェクトを文字列に変換している オブジェクトを文字列に変換するメソッドをオーバーライドしておくと 簡単に出力できて便利 例 ) class Card { } int id; public String tostring() { } return ""+id;
配列の宣言 Java で配列を宣言するときは (C 言語と異なり ) 配列の大きさを宣言しない int a[]; a = new int[10]; // こういう宣言をする ここでは 大きさを書かない // int が 10 個入る配列を作って a に代入する なお 配列に対して.length を参照すると 配列の大きさが分かる 配列の添字に 範囲外の値 ( 負数や大きすぎる値 ) を与えると ArrayIndexOutOfBounds という RuntimeException が発生する 簡単にいうと エラー 後述する
例外とその捕捉 Exception Java には あるメソッド内で例外 ( エラー ) が発生すると そのメソッドの呼出し元に通知される仕組みがある 例外が発生する可能性がある場合 その例外が発生したときの処理 ( 例外処理 ) を書かねばならない 例外処理がないと コンパイルが通らない 例外は try{...}catch(...){...} 構文で捕捉する もしくは さらに上流へ例外を通知する必要がある メソッドの定義に throws の宣言を追加すると そのメソッド内で発生した例外をさらに上流に通知する 捕捉しなくてもコンパイルが通る例外もある (RuntimeException という )
null インスタンスが 無い ことを null で表す null は 値として どのクラス型の変数にも代入できる null に対して メソッドの呼出しや フィールドの参照を行うと NullPointerException という例外が発生する 通称 ぬるぽ NullPointerException は RuntimeException なので 捕捉し忘れることが多い
Thread 計算の実行の流れの一つ一つを thread( スレッド ) と呼ぶ マルチスレッド (multi-thread) は 複数の計算を並行して実行する GUI を使うと GUI を制御するためのスレッドが作られるので 実はマルチスレッドで動くことになる 複数のスレッドから一つのデータを参照したり書き換えようとするときには 排他制御を必要とする Java では synchronized というキーワードを使って排他制御を行うことができる ( 第 9 回で解説予定 )
サンプルプログラムをいくつか 授業の Web ページにサンプルプログラムを置いた (http://sun.ac.jp/prof/yamagu/2017oop/ の今日の日付のあたり ) 2017OOPsamples.tgz というファイルをダウンロードする シェルで tar zxf 2017OOpsamples.tgz を実行して展開する 展開すると samples2017 というディレクトリが作られる samples2017 の下に audio, file, gui, network, random の各ディレクトリがある 各ディレクトリにある.java ファイルのコメントを参考にコンパイルと実行をしてみるとよい ) 日本語を使っているので コンパイル時に文字コードを 指定する必要がある
最終課題に向けた演習時間 各自 自分の課題に向けた 作業をしてください
出席確認演習 最終課題に向けた演習時間中に行ったことを簡単に報告しなさい 提出方法 :sec02@sun.ac.jp 宛にメール 提出期限 : 今日中