Report5




Report5
		2003/12/11
		
		!!!  This Page Is Made By Shift JIS  !!!



   
    report5:講義資料オブジェクト指向プログラムJavaI&JavaIIの中のサンプルプログラム
        について考察せよ{〜12/15(Mon)}
                講義資料サンプルプログラムの考察については、
                ローカル変数以降interfaceまでとする。
   



もくじ

色々な変数

色々なメソッド&アクセス

継承

感想&反省












継承
継承とは:既存のクラスを元にして新しいクラスを作る事です。

継承で新しいクラスをつくる事により、元のクラスのメソッドや、クラス変数を使う事ができます
この元になるクラスの事を、スーパークラスと言います。
反対に新しく作られるクラスの事を、サブクラスと言います。

継承を具体的な例をあげて説明すると
例えば、『薬草』があるとする、
この薬草から『食べ物』や『薬』が作れる
この食べ物や薬は薬草の特徴を受け継いでいます。図で表すと↓のようになります

という関係が成り立ちます。
この関係をプログラムで表現する方法が『継承』です。
『薬草』(スーパークラス)の持つ特徴(栄養、繊維etc..)等を (メンバ変数、メソッドetc...として)
『食べ物』や『薬』等(サブクラス)が引き継いでいます。
プログラムで上での関係を図で表すと↓の用になります。


サブクラスは一つのスーパークラスからいくつでも作る事ができます。
しかし、サブクラスが継承できるスーパークラスはひとつだけです。
これを単一継承と呼びます。クラスは継承される事で枝葉を広げていく
ツリー形の構造になっています。

スーパークラスを継承したサブクラスをスーパークラスとしてサブクラスを作る事も可能です
つまり、サブクラスのサブクラスを作る事ができます。
しかし、子孫の変数やメソッドは使えません。つまり、インスタンス化されたクラスが
スーパークラスから継承した機能しか利用できません。
ちなみにコンストラクタも継承されません、コンストラクタはそのクラス固有のものです。

継承時にメンバ変数名、メソッド名が重なったら、インスタンス化されたクラスから
最も近い階層のスーパークラスの定義が使われます。つまり、継承時に既存のメンバ変数
メソッドを変更する事ができます。
この変更する事をメソッドをオーバーライドすると言います。

継承&オーバーライドのプログラム
[Mi:eclipse/workspace/report] j03040% java List Extend.java
File name:Extend.java
 1:/*
 2: * day: 2003/12/11
 3: * @author: j03040
 4: * @ST-ID :035740F
 5: */
 6:class herb{              //スーパークラス『薬草』
 7:     int g=30;
 8:     public void Print(){
 9:             System.out.println("just Herb!");
 10:    }
 11:}
 12:
 13:class food extends herb{       //サブクラス『食べ物』
 14:    public void Print(){       //オーバーライド
 15:            super.Print();     //super
 16:            System.out.println("birds eating");
 17:    }
 18:}
 19:class drug extends herb{       //サブクラス『薬』      
 20:    drug(){
 21:            System.out.println("Doctor give mi "+g+"g durg!");
 22:    }
 23:    public void Say(){
 24:            System.out.println("Sinsemila!");
 25:    }
 26:}
 27:public class Extend {
 28:    public static void main(String[] args) {
 29:            food obj1=new food();       //オブジェクト生成
 30:            System.out.println("herb ---> food");
 31:            obj1.Print();               //food.Printの実行
 32:            drug obj2=new drug();       //インスタンス生成
 33:            System.out.println("hreb ---> drug");
 34:            obj2.Say();                 //drug.Sayの実行
 35:            obj2.Print();               //Printの実行
 36:    }
 37:}

実行結果
[Mi:eclipse/workspace/report] j03040% java Extend
herb ---> food
just Herb!
birds eating
Doctor give mi 30g durg!
hreb ---> drug
Sinsemila!
just Herb!


13:&19:でextendsを使ってherbを継承しています。
14:ではherbの中のPrintをオーバーライドして再定義しています。
オーバーライドしているので、30:でPrintを実行しても、
herbのPrintではなくてfoodのPrintを実行しています。
しかし、35:で呼び出されたPrintはdrug内でオーバーライドされていないので
herbのPrintが実行されています。

21:でdurg内では定義されてないgという変数を使っていますが、
これはherbから受け継いだ変数なのでこういう風に使えています。


food内でPrintをオーバーライドしたけど、スーパークラスのPrintを使いたい
そんな時に使うのが15:で使っているsuperです。

superとは、サブクラスでオーバーライドされてしまった、メソッド等を使う時に
使用されるキーワードです。

this
インスタンスメソッドやコンストラクタからほかのメソッドや変数を参照する場合
オブジェクト名を指定せず参照する事ができます。
それは現在のオブジェクトを示す、thisを持っているためです。
つまり、thisとは、『現在のオブジェクト』という事を示しています。
普通はこのthisを特別意識することはないですが、
例えば『クラス変数とローカル変数の名前が同じ』等のような時にどの変数か区別するために
thisが必要になってきます。
すこし分かりにくいので例のプログラム
[Mi:eclipse/workspace/report] j03040% java List Extend.java
File name:Extend.java
 1:/*
 2: * day: 2003/12/11
 3: * @author: j03040
 4: * @ST-ID :035740F
 5: */
 6:class herb{ 
 7:     int g=30;
 8:     String color="green";//←新しく追加したところ
 9:     public void Print(){
 10:            System.out.println("just Herb!");
 11:    }
 12:}
      略
 28:class dye extends herb{
 29:    void paint(String m){
 30:            String color=m ;
 31:            System.out.println("dye Color="+color);
 32:            System.out.println("dye Original Color="+this.color);
 33:    }
            略
 45:            dye obj3=new dye();
 46:            System.out.println("hreb --->dye");
 47:            obj3.paint("red");
 48:    }
 49:}

上のExtend.javaにdyeクラスを追加
プログラムを見て分かると思いますが、クラス変数とローカル変数が同じ名前です。
ところがSystem.out.printlnのところは今まで通り+colorとなっています。
さてこの場合どの色が表示されるでしょうか?
実行結果
[Mi:eclipse/workspace/report] j03040% java Extend
略
hreb --->dye
dye Color=red

とredが表示されてしまいました。
クラス変数とローカル変数が同じ名前の場合は
結果的にはローカル変数が優先されてしまいました。
さて、それではgreen(クラス変数)はどこに行ってしまったのでしょうか?
このような場合にthisを使います。
上記のプログラムに↓の一行を加えて実行してみましょう。
System.out.println("dye Original Color="+this.color);

実行結果
略
hreb --->dye
dye Color=red
dye Original Color=green

となりました、このようにthisを使う事で、同じ名前の変数や、メソッドを区別する事ができます。


abstract
abstractはクラス・メソッド宣言時に付与し、クラス・メソッドを
抽象クラス・メソッドにします。
サブクラス内で抽象クラスを継承して、抽象メソッドをオーバーライドして
オブジェクトを生成する形をとります。
分かりにくいので今まで通り具体的な例をあげて説明したいと思います。

薬草(herb)からは薬(durg)や染料(dye)が作れるように、
『紙』(paper)も作れます、しかし、この紙はほかのものと違います。
薬には病気を治すという働き(メソッド)があります。
染料には色を変えるという働き(メソッド)があります。
しかし紙はその名の通り『白紙』なのでそのままではなんの価値もありません(メソッドがない!)
なので、紙に文字を書く(draw)と言う働きや
折り紙(bend)をして、動物を作るという働きを作らなければなりません

と上記が抽象クラス・メソッドの考え方です。
抽象クラスは、共通の働きを表現して、特別な機能はサブクラスで定義したい時に使用します。
つまりpaperクラス(スーパークラス)で紙の色や形、大きさなどの共通の部分を定義して
このクラスを継承するサブクラス(『書く』クラス(draw)や『折り紙』クラス(bend))で
個々に異なる機能を定義するわけです。

abstractのプログラム
上記のExted.javaに追加
[Mi:eclipse/workspace/report] j03040% java List Extend.java
        省略
 35:abstract class paper extends herb{    //抽象クラスpaper
 36:    String size="B4";                     //共通部分 大きさ 
 37:    String  form="square";                //共通部分 形
 38:    abstract void make(int x);            //抽象クラス make
 39:}
 40:class draw extends paper{           
 41:    void make(int x){                   //makeを具体的に定義
 42:            int i,a=5;                  //入力された数だけ*を出力
 43:            for(i=1;i<=x;++i){
 44:                    System.out.print("*");
 45:                    if(i==a){
 46:                            System.out.print("\n");
 47:                            a+=5;
 48:                    }
 49:            }
 50:    }
 51:}
 52:class bend extends paper{
 53:    void make(int x){                 //makeを具体的に定義2
 54:            System.out.println(x*2);  //2倍して出力
 55:    }
 56:}
 57:public class Extend {
 58:    public static void main(String[] args) {
         省略
 69:            System.out.println("hreb --->paper");
 70:            draw draw =new draw();
 71:            bend bend=new bend();
 72:            System.out.println("paper size="+draw.size);
 73:            System.out.println("paper form="+draw.form);
 74:            System.out.println("paper size="+bend.size);
 75:            System.out.println("paper form="+bend.form);
 76:            draw.make(30);
 77:            bend.make(100);
 78:    }
 79:}

実行結果
[Mi:eclipse/workspace/report] j03040% java Extend
     省略
hreb --->paper
paper size=B4
paper form=square
paper size=B4
paper form=square
*****
*****
*****
*****
*****
*****
200

とこのように、共通の部分(size,form)は同じだけど
make()の部分は全然違う、働きをする事が分かる、



interface
interfaceとは:
インターフェースとは、内容に抽象メソッドしか持たない、クラスのようなものです
インターフェースはクラスによって実装(implements)され実装クラスは
インターフェースで宣言されている抽象メソッドを実装します。
簡単に言うとインターフェースはメソッドの集合で、親が異なるクラスに対しても同じメソッド
提供する事ができる。つまり、禁止されている多重継承をやる方法がインターフェースです。

インターフェースの実装方法
class <サブクラス名> extends <親クラス> implement<インターフェースクラス名>

interfaceのプログラム
[Mi:eclipse/workspace/report] j03040% java List Intf.java
File name:Intf.java
 1:/*
 2: * @day: 2003/12/13
 3: * @author j03040
 4: * @ST-Id: 035740F
 5: */
 6:interface drum{       //interface
 7:     void pon(String p);
 8:}
 9:interface hill{       //interface
 10:    int don(int d);
 11:}
 12:public class Intf implements drum,hill{
 13:    public void pon(String p){     //実装
 14:            System.out.println(p);
 15:    }
 16:    public int don(int d){         //実装
 17:            return d*d;
 18:    }
 19:    public static void main(String[] args) {
 20:            int a;
 21:            Intf obj=new Intf();
 22:            obj.pon("no more war");
 23:            a=obj.don(2);
 24:            System.out.println(a);
 25:    }
 26:}

実行結果
[Mi:eclipse/workspace/report] j03040% java Intf
no more war
4

このように、いろいろなメソッドを実装して、使う事ができるのがインターフェースの特徴です




反省・感想


macが壊れて修理いきという苦難を乗り越えて良くがんばったと思う。
emacsが使えずeclipseに乗り換えたり、、、、
大変だった、、、





もくじにもどる