広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2012年01月16日

   Java総合講座 - 初心者から達人へのパスポート
                 2009年11月開講コース 054号

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:vol.xxx(xxxは番号)が振られています。
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


========================================================
◆ 01.グラフィックスのプログラミング
========================================================

今回からは、グラフィックス(graphics)すなわち図形や絵を
描くプログラムを作っていきます。
合わせてアプレット(Applet)についても学んでいきましょう。


アプレットはWebページの中に組み込まれる形式のJavaのプログ
ラムで、Webページといっしょにインターネットからダウンロー
ドされ、Webブラウザーで実行されます。
(なお、Webブラウザーの他に「アプレット・ビューア」という、
アプレットの実行だけに特化されたブラウザーがJDKに用意され
ており、アプレットのテスト時にはこれも使用されます。)

(サイズが大きいとダウンロードに時間がかかってしまうので
好ましくありませんから)アプレットはサイズの小さいものが
望ましいです。
そもそもアプレット(Applet)という言葉はapplicationとletを
組み合わせて作られた造語で、letは小さいことを意味する接尾辞
です(たとえばbookletが小冊子を意味するように)。
つまり「小さなアプリケーション」というようなイメージの単語に
なっています。
しかし、アプレットのサイズに制限があるわけではなく、アプレッ
トの仕様と名前のイメージには関係はありません。


アプレットの登場によって、それまで静的だったWebページが、動き
のある活気あるものに変わってきましたので、当初、アプレットは
Javaの代名詞と言えるくらい人気を博しましたが、現在はアプレット
に置き換わるものとしてFlash、さらにはAjaxが普及しており、アプ
レットは下火になりつつあります。

しかしながら、Flashのアプリケーションを作るためには開発環境
を有料で用意しなければなりませんし、Ajaxよりもアプレットを
使ったほうがグラフィックスなども自由自在に操作できてプログラ
ミングが楽ですので、依然としてアプレットにはメリットがありま
す。けっしてアプレットを使う場面が無くなったわけではありませ
ん。
またJavaの基本知識の一つですから、Javaを学ぶ者はアプレットに
ついても知っておく必要があります。
(Ajaxは、JavaScriptという、Javaをモデルにして作られたスクリ
プト言語をベースに使う技術なので、Javaそのものではありません
が、重要な技術なので当メールマガジンでも後に学ぶことにします。)

というわけで、アプレットの作り方も学習しておきましょう。


アプレット自身の詳しい説明は後の記事に回すことにして、今回は
ひとまず簡単なアプレットを作って、イメージをつかんで頂くこと
にします。


さて、アプレットは、java.awtパッケージのAppletというクラスの
サブクラスとして作成します。逆に、Appletのサブクラスとして
作成しなければアプレットと呼ぶことはできません。
Swingを使いたい場合は、AppletのSwing版サブクラスとしてJApplet
というクラス(javax.swingパッケージ)が用意されていますので、
JAppletのサブクラスとして作成することになります。


一方、Javaでグラフィックスを作成するためにはGraphicsというクラ
スを使用します。
Graphicsはグラフィックスに関するコンテキスト(context = 日本語で
は文脈と訳されることが多いが、正確に言うと文脈だけに限らず、我々
が行動するときに関与する周辺の関連情報一般を意味する。日本語には
これと一対一に対応する単語がないので「コンテキスト」というふうに
カタカナ書きで表記しておく)一切をクラスにしたものです。
このクラスを使うとGUI部品上に絵や図形を描いたり、文字を描くこと
もできます。

しかし、Graphicsは抽象クラス(抽象クラスについては後で解説する)
なので、我々がインスタンスを生成することはできません。

GraphicsのインスタンスはGUI部品(Component)のgetGraphics()という
メソッドを呼び出して取り出すというルールになっています。

今回は、Graphicsの

setColor(色)

というメソッドを使って色を設定し、Graphicsの

drawLine(始点のX座標, 始点のY座標, 終点のX座標, 終点のY座標)

というメソッドを使って直線(線分)を描くという操作を行います。



まず今回は、超簡単な(安直でかなりいい加減な)お絵描き(落書き)
ソフトを作ってみましょう。
マウスをドラッグするとその軌跡を描くだけの簡単なお絵描きソフト
です。


では、Eclipseを起動してください。

(1) パッケージ・エクスプローラーの中のJStudy1を右クリックし、
「新規」→「その他」を選択します。

(2) 「新規」ウインドウにおい「WindowBuilder」配下の
「Swing Designer」配下の「JApplet」を選択し、「次へ」ボタンを
クリックします。

(3)  「ソース・フォルダー」に「JStudy1/src」が入力されていること
を確認し、「パッケージ」に

jp.co.flsi.lecture.cg

と入力し、「名前」の欄に

GraffitiApplet

と入力しましょう。

(4) 「スーパークラス」が「javax.swing.JApplet」になっていることを確認し、
「完了」ボタンをクリックします。


GraffitiApplet.javaのエディターが開きましたら、以下のようにソース・
コードを編集しましょう。


(1) 点の座標を表すフィールドを下記のように宣言します。
--------------------------------------------------------
private int pointX;
private int pointY;
--------------------------------------------------------

(2) 線の色を表すフィールドを下記のように宣言します。
--------------------------------------------------------
private Color lineColor = Color.BLUE;
--------------------------------------------------------
(Colorクラスのパッケージのimport文は例によってコンテンツ・アシスト
の機能(Ctrlキー+スペース・キー)を使って追加しましょう。
このColorというクラスはjava.awtパッケージにはいっています。)
BLUEはColorのstaticフィールドで、文字通り青色を表します。

(3) 次の2つのメソッドを追加しましょう。
--------------------------------------------------------
public void setPoint(MouseEvent e) {
   pointX = e.getX();
   pointY = e.getY();
}

public void drawLine(MouseEvent e) {
   Graphics g = getGraphics();
   g.setColor(lineColor);
   g.drawLine(pointX, pointY, e.getX(), e.getY());
   setPoint(e);
}
--------------------------------------------------------
(MouseEventというクラスはjava.awt.eventパッケージにはいっています。
またGraphicsというクラスはjava.awtパッケージにはいっています。)

このうちsetPoint(MouseEvent e)メソッドはMouseEventが持って
いるマウスの位置情報(X座標とY座標)を変数pointXとpointYに
代入します。
また、drawLine(MouseEvent e)メソッドは描画するときの色を
lineColorに設定された色にし、pointX, pointYで示される点から
マウスの現在の位置情報で示される点まで直線(線分)を引きます。
その後、setPoint()メソッドを呼び出してマウスの現在の位置情報
を変数pointXとpointYに代入し直します。
なお、MouseEventクラスのgetX()、getY()メソッドは、MouseEvent
オブジェクトが持っているマウスの位置情報のX座標、Y座標を取り
出すためのメソッドです。
メソッドの詳細を知りたい場合は、前々回紹介したAPI仕様のWebページ

http://java.sun.com/javase/ja/6/docs/ja/api/index.html

などで調べて下さい。(各自の自主演習とします。)


次にDesignビューを開いて(エディターの画面は最大化しておきましょう)、
アプレット(灰色の四角形)の中を右クリック
し、「Add event handler」→「mouse」→「mousePressed」を選択します。

すると、下記のソース・コードが生成されますね。
--------------------------------------------------------
      getContentPane().addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
         }
      });
--------------------------------------------------------
このイベント・リスナーのmousePressed()メソッドは文字通りマウス
のボタンを押したときに呼び出されるメソッドです。

これを次のように編集しましょう。
--------------------------------------------------------
      getContentPane().addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
            setPoint(e);
         }
      });
--------------------------------------------------------
マウスのドラッグを始める最初の時点ではマウスのボタンを押しますから、
その時点でこのmousePressed()が実行され、したがってsetPoint()が実行
されることになります。
つまりドラッグの始まりの点の座標がpointX, pointYに設定されることに
なります。


再度Designビューに戻り、アプレット(灰色の四角形)の中を右クリックし、
「Add event handler」→「mouseMotion」→「mouseDragged」を選択します。

すると、下記のソース・コードが生成されますね。
--------------------------------------------------------
      getContentPane().addMouseMotionListener(new MouseMotionAdapter() {
         @Override
         public void mouseDragged(MouseEvent e) {
         }
      });
--------------------------------------------------------
このイベント・リスナーのmouseDragged()メソッドは文字通りマウスを
ドラッグしたときに呼び出されるメソッドです。
マウスの移動が検知されるたびに呼び出されますので、マウスをドラッ
グしている間に何度も呼び出されることになります。ただし、どのくら
い細かくマウスの移動を検知できるかは、ハードウエアに依存しますの
で、具体的な数値を述べることはできません。

これを次のように編集しましょう。
--------------------------------------------------------
      getContentPane().addMouseMotionListener(new MouseMotionAdapter() {
         @Override
         public void mouseDragged(MouseEvent e) {
            drawLine(e);
         }
      });
--------------------------------------------------------
こうすると、mouseDragged()メソッドが呼び出されるたびにdrawLine()
メソッドが呼び出され、したがって、マウスの移動が検知されるたびに
前のマウスの位置情報で示される点と現在のマウスの位置情報で示され
る点との間に線が引かれることになります。



はい。では、保管してからテストしてみましょう。
パッケージ・エクスプローラーの中のJStudy1の配下の(さらにsrcの配下の)
jp.co.flsi.lecture.cgの中のGraffitiApplet.javaを右クリックし、
「実行」→「Javaアプレット」を選択します。
(「警告: AppletViewer プロパティファイルが読み込まれません:
C:\Users\future\.hotjava\properties デフォルトを使用します。」という
メッセージが表示されるかも知れませんが、これは無視して下さい。)

アプレット・ビューア(Eclipseでは、デフォルトとしてJDKに含まれている
アプレット・ビューア(applet viewer)が自動的に使用される)が開きます
ので、その中でマウスをドラッグして落書きをしてみてください。

ドラッグする通りに曲線(細かく言うと折れ線だが、大雑把に見ると曲線
に見える)が描かれることが確認できますね。


でも、青い線だけしか描けないのでは、つまらないですね。
色を変えられるようにしてみましょう。
(アプレット・ビューアは「閉じる」ボタン(×マークのボタン)を押して
閉じて下さい。)


まず、このアプレットのLayoutManagerはデフォルトがBorderLayoutになって
いますので、GUI部品を好きなところに貼り付けられるようにするために
LayoutManagerをnullに変えておきましょう。

Designビュー上でアプレットの中を右クリックし、「Set Layout」→
「Absolute layout」を選択します。
これでLayoutManagerがnullに設定されます。


次にPalette(パレット)から(Componentsの)JToggleButtonを取り出して
アプレット内の左上のほうに貼り付けましょう。
変数名(Properties欄のVariable)はredToggleButtonにしておきましょう。

このredToggleButtonの下にさらにJToggleButtonを2つ貼り付け、それぞれ
greenToggleButtonおよびblueToggleButtonという変数名にしておきま
しょう。
つまり、JToggleButtonが全部で3個、縦に並ぶように貼り付けるわけです。

きれいに並んでいなくても大丈夫です。後で位置を調整しますので。


続いてこれらのJToggleButtonに色を付けましょう。また、色の文字を表示
させるようにしましょう。

(1) redToggleButtonをクリック(あるいはStructure欄のredToggleButton
を選択)することによって、Properties欄にredToggleButtonのプロパティー
を表示させます。(Designビューの画面上ではハンドルが表示される位置と
ボタンの絵が表示される位置にずれが生じるようですが、気にしないで下さい。
ボタンの幅や高さを変えるための操作はこれまでと同様にハンドルの方をドラッ
グして行います。)

(2) その中のbackgroundプロパティーを選択し、その右端のボタンをクリックし、
「Color chooser」ウインドウの中の「AWT colors」タブを選択して
色のリストの中から「RED」を選択し、「OK」ボタンをクリックします。

(3) textプロパティーの値を「赤」に設定しましょう。

(4) サイズが小さいと「赤」という文字が表示されませんから、文字が表示
されるように四隅のハンドルをドラッグしてJToggleButtonのサイズを大きく
しておいてください。

以下、同様にして、greenToggleButtonのbackgroundプロパティーを「GREEN」、
textプロパティーの値を「緑」に、blueToggleButtonのbackgroundプロパティー
を「BLUE」、textプロパティーの値を「青」にしてください。


この3つのJToggleButtonをきれいに並べさせるためには、次のように操作を
してください。

(1) 一つ目のJToggleButtonをクリックします(ボタンの位置とハンドルが表示
される位置がずれている場合、クリックするのはハンドルが表示される位置の
方ですので注意して下さい)。

(2) 二つ目のJToggleButtonはCtrlキーを押しながらクリックします。

(3) 三つ目のJToggleButtonもCtrlキーを押しながらクリックします。
これでGUI部品が複数選択された状態になります。(このうち最後に選んだ
GUI部品をアンカー・コンポーネント(anchor component)と呼び、位置など
を揃えるときの基準になります。)

(4) Designビューの右上のほうにあるアイコンのうち、「Replicate width
(幅の複製)」というアイコン(マウス・ポインターを乗せると
「Replicate width」という文字列が表示されるボタン)をクリックします。
これでこれらのボタンの幅が揃います。
(なお、幅を伸縮させたいときは右端(あるいは左端)のハンドルをドラッグ
して行います。)

(5) 同様に、「Align left edges(左端揃え)」ボタン(マウス・ポインター
を乗せると「Align left edges」という文字列が表示されるアイコン)を
クリックしましょう。これでこれらのボタンの左端が揃います。

(6) 同様に「Space equally, vertically(上下方向の等間隔割り付け)」ボタン
をクリックしましょう。これでこれらのボタンが上下方向に等間隔に並びます。

(他にも同様のボタンがいくつかありますが、そのアイコンと(マウス・ポインター
を乗せたときに表示される)名称からそれぞれのボタンの機能は推測できるでしょう。
各自、自主的に試して探索してみて下さい。)


これで、3つのJToggleButtonがきれいに勢揃いしましたね。


このうち、最初はblueToggleButtonが選択されている状態にしたいので、
blueToggleButtonをクリックし、Properties欄のselectedプロパティーを
選択して、その値をtrueに変更してください。(デフォルトではfalseが
表示されているはずですが、そこをダブル・クリックするとチェック・
マークが付きtrueに変わります。)


これら3つのJToggleButtonは、ラジオ・ボタンのように同時に一つだけ
しか選択できないようにしたいので、以下の手順で、これらを一つの
ButtonGroupに登録することにしましょう。

(1) ソース・コード上で
      JToggleButton redToggleButton = new JToggleButton("\u8D64");
という行を探し、この中のredToggleButtonという変数にカーソルを入れ、
メニュー・バーから「リファクタリング」→「ローカル変数をフィールドに変換」
を選択します。

(2) 「ローカル変数をフィールドに変換」ウインドウで「OK」ボタンを
クリックします。
以上でredToggleButton変数が他のメソッドからもアクセス可能になります。

(3) 同様の操作(上の(1),(2))を、
      JToggleButton greenToggleButton = new JToggleButton("\u7DD1");

      JToggleButton blueToggleButton = new JToggleButton("\u9752");
の行に行うことによって、greenToggleButtonとblueToggleButtonもフィールド
に変換しておきます。

(4) 下記のようなinit()メソッドをソース・コードを追加します。
(init()はアプレットが起動されたときに最初に1回だけ実行されるメソッ
ドです。)

なお、ButtonGroupクラスはjavax.swingパッケージにはいっています。

--------------------------------------------------------
   public void init() {
      this.setSize(600, 600);
      ButtonGroup group = new ButtonGroup();
      group.add(redToggleButton);
      group.add(greenToggleButton);
      group.add(blueToggleButton);
   }
--------------------------------------------------------

この先頭のsetSize()メソッドの呼び出しは、ToggleButtonを貼り付けた分
画面を広くする必要があったのと、画面をできるだけ広くしてお絵描きを
しやすくするために画面を拡大しています。

それに続くButtonGroupのadd()メソッドの呼び出しによって、redToggleButtonと
greenToggleButtonとblueToggleButtonの三つのToggleButtonを一つのButtonGroup
に登録してグループ化しています。



では、これらのボタンを選択すると、それ以後引く線の色がそのボタンの
色になるようにプログラミングしましょう。

まず、Designビューの中でredToggleButtonを右クリック(ハンドルが表示される
位置とボタンの位置がずれているでしょうから、ハンドル表示される位置のほうを
右クリック)して、「Add event handler」→「アクション」→「actionPerformed」
を選択します。

すると、ソース・コードに以下のコードが自動的に追加されますね。

--------------------------------------------------------
      redToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
         }
      });
--------------------------------------------------------

これを以下のように編集しましょう。
--------------------------------------------------------
      redToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            lineColor = new Color(255,0,0);
         }
      });
--------------------------------------------------------
(なお、「lineColor = new Color(255,0,0);」の代わりに
「lineColor = Color.RED;」としても同じです。)


同様に操作して、greenToggleButtonとblueToggleButtonに対しても
それぞれ、
--------------------------------------------------------
      greenToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            lineColor = new Color(0,255,0);
         }
      });
--------------------------------------------------------

--------------------------------------------------------
      blueToggleButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            lineColor = new Color(0,0,255);
         }
      });
--------------------------------------------------------
を追加しましょう。

(それぞれ、「lineColor = new Color(0,255,0);」の代わりに
「lineColor = Color.GREEN;」、「lineColor = new Color(0,0,255);」
の代わりに「lineColor = Color.BLUE;」としても同じです。)



では保管したあと、GraffitiAppletを実行してテストしてみましょう。

最初は青色が選択されており(選択状態にある青のボタンは青色には
ならない)、線を引いてみると青色の線になりますが、色のボタンを
クリックしてから線を引いてみると、その色の線になることが確認でき
ますね。


たった3つの色ボタンでは、つまらない・・・という人は自分で他の色の
ボタンもたくさん貼り付けてプログラミングしてみてください(これは
演習にします)。


ところで、このお絵描きソフトはいい加減なので、次回からはきちんと
したお絵描きソフトを作ることにしましょう。



では、今回はここまで。


(続く)



========================================================
◆ 02.文法解説 [抽象クラス]
========================================================

[抽象クラス]

我々人間は哺乳類の一種ですね。
哺乳類は、ヒト、イヌ、コウモリ、クジラなどのスーパークラスと見なす
ことができますが、この哺乳類というのは、便宜的に作られた分類上の
クラス(種類)であって、抽象的な概念に過ぎません。
すなわち、ヒト、イヌ、コウモリ、クジラなどの哺乳を行う動物の共通な
特性だけを抽出した概念に過ぎず、具体性に欠ける概念になっています。

具体性に欠けるというのは、たとえば、移動方法を考えると、ヒトは2本足
で移動し、イヌは4本足で移動し、コウモリは飛んで移動し、クジラは水中
を泳いで移動しますが、それらのスーパークラスである哺乳類は具体的に
どのように移動するのか明確ではありません。
(これはプログラム上では移動のメソッドが実装されていないことを意味し
ます。)
このような不明確性を持つ抽象的なクラスは、抽象クラス(abstract class)
と呼ばれます。

インスタンスはクラスの具体例なので、振る舞いが不明確であることは
許されず、したがって抽象クラスのインスタンスを生成することは許さ
れません。

というわけで、Javaでは、抽象クラスは、インスタンスを生成できない
クラスを意味します。


抽象クラスは、

--------------------------------------------------------
public abstract class NantokaKantoka {
   .
   .
   .
}
--------------------------------------------------------

のようにclass定義にabstractという修飾子を指定することによって表し
ます。

抽象クラスは、実装されていないメソッドを含むことができ、この実装
されていないメソッドを抽象メソッドと呼びます。
たとえば、さきほどの「移動」するという振る舞いをmove()というメソッ
ド名で表すことにすると、哺乳類(Mammal)のクラスではmove()メソッド
は実装できませんので、抽象メソッドにします。

この場合、ソース・コード上では

--------------------------------------------------------
public abstract class Mammal {
   .
   .
   public abstract void move();
   .
   .
}
--------------------------------------------------------

のように、抽象メソッドはabstractという修飾子をつけることによって
表し、実装部分はなく、代わりにセミコロン(;)でメソッドの定義を終わ
らせます。

(ちなみに、インターフェース(021号参照)に指定されるメソッドは
すべて抽象メソッドに決まっているので、インターフェースにおいては
abstractは省略されます。)

抽象クラスは抽象メソッドを持つという点ではインターフェースと同じ
ですから、インターフェースと同じような使い方(021号参照)もでき
ますが、基本的には異なる目的で使用されます。
(抽象クラスをインターフェースと同じ目的で使用すべきではありません。)

抽象クラスは、各サブクラスの共通部分を抽出して抽象クラスにまとめる
ことによって各サブクラスで重複した実装を無くすことが目的(これは
スーパークラスを作ることの目的)で、この場合、抽象メソッドは多様性
(polymorphism)を表現する手段です。
つまり、抽象メソッドは「サブクラスによって振る舞いが違うから必ず
サブクラスごとにこのメソッドを実装する必要がある」ということを示す
働きがあります。

一方、インターフェースはクラスの概念とは関係なく、オブジェクトの
呼び出し方を規定して開発の利便性を向上するために作るもので、クラス
の開発者とクラスの利用者が互いに独立して開発を進められるようにする
ことが目的です。

したがって、インターフェースはクラスの開発やクラスを利用する側のプ
ログラムの開発の前に作成しておかなければならないのに対し、抽象クラ
スはクラスの開発途中や開発後のリファクタリングの過程でも作成する
ことができます。


ところで抽象クラスのサブクラスを作成するときには、抽象メソッドは
必ず実装しておかなければなりません。さもなければコンパイル・エラー
になります。
ただし、サブクラスも抽象クラスにしてしまえば抽象メソッドを実装する
必要はなくなります。

たとえば、Mammalのmove()は抽象メソッドにしましたが、移動という振る
舞いはMammalだけのものではなく、脊椎動物や無脊椎動物を含む動物
(Animal)全般が移動という振る舞いを行います。したがって、Animalク
ラスをMammalクラスのスーパークラスとして用意し、move()をAnimalクラ
スに移し変え、以下のようにしてみます。

--------------------------------------------------------
public abstract class Animal {
   .
   .
   public abstract void move();
   .
   .
}
--------------------------------------------------------
public abstract class Mammal extends Animal {
   .
   .
   .
   .
}
--------------------------------------------------------

このようにMammalを抽象クラスにしている限りmove()メソッドを実装して
いなくても問題はありませんが、もしMammalのクラス定義からabstract修
飾子を取り除くと、move()メソッドを実装していないことでコンパイル・
エラーになります。



下表に抽象クラスとインターフェースの違いを比較します。

インターフェース(interface) 抽象クラス(abstract class)
--------------------------------------- --------------------------------------
メソッドの実装がない 実装されたメソッドも持てる
publicメンバーのみ privateやprotectedのメンバーも持てる
複数のインターフェースをextends可能 extendsできるクラスは一つだけ
フィールドはstaticでfinal(固定値)のものに限る フィールドは何でも定義できる

(上記の「メンバー」とはフィールドやメソッドのこと)



上の比較表において「複数のインターフェースをextends可能」について解説
しておきます。

クラスにスーパークラスとサブクラスがあるようにインターフェースにも
スーパーインターフェース(superinterface)とサブインターフェース
(subinterface)があります。
クラスと同じようにextendsキーワードによってスーパーインターフェース
を指定します。

このとき、インターフェースの定義ではスーパーインターフェースは複数
指定することができるのに対し、クラスの定義にはスーパークラスは1つ
しか指定できません。

これはなぜかというと、Javaでは多重継承が禁止されているからです。
多重継承(multiple inheritance)とは、スーパークラスを複数持つことを
意味します。
たとえば、ラジカセがラジオとカセットレコーダーの2つのクラスのサブク
ラスであると考えるとラジオとカセットレコーダーの2つのクラスを多重継承
していることになります。

しかし、多重継承には難点があります。
たとえば、ラジオのクラスとカセットレコーダーのクラスの両方にplay()と
いうメソッドがあるとすると、それらを継承したラジカセのplay()メソッド
を呼び出そうとしたときに、いったいラジオのplay()メソッドが実行される
のかそれともカセットレコーダーplay()メソッドが実行されるのか、どちら
が実行されるのか混乱してしまいます。

このように多重継承には難点があるためにJavaでは多重継承は禁止されました。
つまりJavaのクラスは1つのスーパークラスだけしか持つことはできません。

では、ラジオのクラスとカセットレコーダーのクラスがあったときに、これら
2つのクラスを合成してラジカセを作るためにはどうしたらいいかというと、
一方を継承し、他方を内部に組み込んだ複合オブジェクトとして作ればいいの
です。
つまり、ラジオのサブクラスにカセットレコーダーを組み込んだ形にするか、
あるいはカセットレコーダーのサブクラスにラジオを組み込んだ形にします。
このようにすれば、多重継承などしなくても(スーパークラスが1つでも)
複数のクラスから新しいクラスを合成することができます。


一方、インターフェースは複数のスーパーインターフェースを持つことがで
きます。
たとえば
--------------------------------------------------------
public interface InterfaceX extends InterfaceA, InterfaceB {
   .
   .
   .
   .
}
--------------------------------------------------------
というふうに。
これはなぜかというと、インターフェースはメソッドの実装を含まない(抽象
メソッドだけしか持たない)ために、実行されるメソッドはクラスで実装され
たもの一つだけに決まり、混乱が生じないからです。


また、インターフェースのメソッドは、クラスで実装する必要があるわけですが、
クラスで実装するインターフェースは複数指定することができます。
たとえば、
--------------------------------------------------------
public class ClassImp implements InterfaceA, InterfaceB {
   .
   .
   .
   .
}
--------------------------------------------------------
というふうにimplementsの右側にインターフェースを複数指定することができ
ます。



(続く)



================================================
◆ 03.演習問題
================================================

1.
GraffitiAppletに赤・緑・青だけでなく、黄色と黒色も使えるようにしてみて
ください。

[ヒント]
黄色は
lineColor = Color.YELLOW;
または
lineColor = new Color(255,255,0);

黒色は
lineColor = Color.BLACK;
または
lineColor = new Color(0,0,0);

とします。



2.
上記の抽象クラスの働きを確認するために、下記のような複数のクラスを作り、
AbstractClassTestのほうを実行してみてください。

--------------------------------------------------------
public abstract class Animal {
   public abstract void move();
}
--------------------------------------------------------
public abstract class Mammal extends Animal {
}
--------------------------------------------------------
public class Bat extends Mammal {
   public void move() {System.out.println("空中をパタパタと飛ぶ。");}
}
--------------------------------------------------------
public class Whale extends Mammal {
   public void move() {System.out.println("水中をスイスイと泳ぐ。");}
}
--------------------------------------------------------
public class AbstractClassTest {
   public static void main(String[] args) {
      Whale aWhale = new Whale();
      aWhale.move();
   }
}
--------------------------------------------------------

次に、一時的にMammalのabstract修飾子を取り除いてコンパイルし直してくだ
さい。どうなりますか。(確認が終わったら元に戻す。)

同じく一時的にBatのmove()メソッドを取り除いてコンパイルし直してください。
どうなりますか。(確認が終わったら元に戻す。)

今度は、Whaleにabstract修飾子をつけてコンパイルし直してください。どうな
りますか。(AbstractClassTestのほうを確認する。)



(次回に続く。)



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2011 Future Lifestyle Inc. 不許無断複製