【レポート】既存クラスの資産を継承して新しいクラスを作る

【レポート】既存クラスの資産を継承して新しいクラスを作る

目的

既存クラスの資産を継承して新しいクラスを作るクラスの派生と、それを応用した多様性について理解し、使えるようにする。

内容

2つ以上のメソッドを持つStudentクラスを作成して、そこから派生させたHoseiStudetクラスを作成する。また、これらのクラス群と異なるパッケージで、任意のクラスと、そこから派生したクラスを作成する。実行するmainのあるクラスは、別途で作成する。

ソースプログラム

以下にStudentクラスとそこから派生したHoseiStudentクラス、違うパッケージのSchoolInformationクラスとそこから派生したStudentInformationクラス、mainを含んだTesterクラスのソースプログラムを以下に示す。

Studentクラス

package lesson10;

import java.util.Scanner;

public class Student {

Scanner stdIn=new Scanner(System.in);//グローバル

private int gakunen;

private String universityname;//HoseiStudentクラスで初期化される

private String name;

private int age;

//コンストラクタ

public Student(int age){

        this.age=age;

}

//クラスメソッド

public int getAge(){

        return age;

}

//クラスメソッド

public int university(){

        System.out.println(“あなたはどこの大学生ですか?”);

        System.out.println(“法政・・・1  明治・・・2   慶應・・・3   その他・・・4”);

        System.out.println(“相当する大学の番号1~4を入力してください”);

        int x=stdIn.nextInt();

        if(x==1){

          System.out.println(“あなたは法政大学の学生さんですね”);

          name=”法政大学”;

        }

        if(x==2){

          System.out.println(“あなたは明治大学の学生さんですね”);

          name=”明治大学”;

        }

        if(x==3){

          System.out.println(“あなたは慶應大学の学生さんですね”);

          name=”慶應大学”;

        }

        if(x==4){

          Scanner stdIn=new Scanner(System.in); //ローカル

          System.out.println(“どこ大学ですか?”);

          name=stdIn.nextLine();//スペースを含めた1行分の入力を文字列として読み込む

          System.out.println(“あなたは”+name+”大学の学生さんですね”);

        }

          return x;//ここに書かないとエラーがおきる!!

}

}

HoseiStudentクラス

package lesson10;

import java.util.Scanner;

public class HoseiStudent extends Student {

   private String number;//クラス変数

   private String gakubuname;//クラス変数

   public HoseiStudent(int age,String number,String gakubuname){ //Studentクラスでコンストラクタを定義するとこのクラスではsuper()を使って定義しなければならない

           super(age);//派生利用

           this.number=number;

           this.gakubuname=gakubuname;

   }

   //クラスメソッド

   public String getNumber(){

         return number;

   }

   //クラスメソッド

   public String getGakubuname(){

         return gakubuname; 

   }

   //クラスメソッド

   public void kyanpasu(){

        System.out.println(“あなたのキャンパスを調べます”);

        System.out.println(“法・文・経営・国際文化・人間環境・キャリアデザイン・デザイン工学部・GIS・・・1”);

        System.out.println(“経済・社会・現代福祉・スポーツ健康学部・・・2”);

        System.out.println(“工学部・情報科学部・理工学部・生命科学部・・・3”);

        System.out.println(“相当する学部の番号1~3を入力してください”);

        Scanner stdIn=new Scanner(System.in);

        int x=stdIn.nextInt();

        if(x==1){

             System.out.println(“あなたは市ヶ谷キャンパスですね”);

        }

        if(x==2){

             System.out.println(“あなたは多摩キャンパスですね”);     

        }

        if(x==3){

                 System.out.println(“あなたは小金井キャンパスですね”);

        }

 }

}

SchoolInformationクラス

package lesson10.id;

import lesson10.Student;

import lesson10.HoseiStudent;

//インポートをすることによりこのクラスからStudentクラス,HoseiStudentクラスを利用できる

public class SchoolInformation {

protected long gakuhi;//privateはだめ!!

//クラスメソッド

public long expense(HoseiStudent HS){

        if(HS.getGakubuname()==”法学部”){

                System.out.println(“76万円です”);

                  gakuhi=760000;

        }

        if(HS.getGakubuname()==”文学部”){

                System.out.println(“76万円です”);

                  gakuhi=760000;

        }

        if(HS.getGakubuname()==”経済学部”){

                System.out.println(“76万円です”);

                 gakuhi=760000;

        }

        if(HS.getGakubuname()==”社会学部”){

                System.out.println(“76万円です”);

                 gakuhi=760000;

        }

        if(HS.getGakubuname()==”経営学部”){

                System.out.println(“76万円です”);

                 gakuhi=760000;

        }

        if(HS.getGakubuname()==”人間環境学部”){

                System.out.println(“76万円です”);

                 gakuhi=760000;

        }

        if(HS.getGakubuname()==”現代福祉学部”){

                System.out.println(“76万円です”);

                 gakuhi=760000;

        }

        if(HS.getGakubuname()==”キャリヤデザイン学部”){

                System.out.println(“76万円です”);

                 gakuhi=760000;

        }

        if(HS.getGakubuname()==”国際文化学部”){

                System.out.println(“85万円です”);

                 gakuhi=850000;

        }

        if(HS.getGakubuname()==”グローバル教養学部”){

                System.out.println(“100万円です”);

                 gakuhi=1000000;

        }

        if(HS.getGakubuname()==”工学部”){

                System.out.println(gakuhi+”万円です”);

                 gakuhi=1080000;

        }

        if(HS.getGakubuname()==”情報科学部”){

                System.out.println(“108万円です”);

                 gakuhi=1080000;

        }

        if(HS.getGakubuname()==”理工学部”){

                System.out.println(“108万円です”);

                 gakuhi=1080000;

        }

        if(HS.getGakubuname()==”生命科学部”){

                System.out.println(“108万円です”);

                 gakuhi=1080000;

        }

        if(HS.getGakubuname()==”デザイン工部”){

                System.out.println(“108万円です”);

                 gakuhi=1080000;

        }

        if(HS.getGakubuname()==”スポーツ健康学部”){

                System.out.println(“81万円です”);

                 gakuhi=810000;

        }

        return gakuhi;

}

}

StudentInformationクラス

package lesson10.id;

//SchoolInformationからの派生クラスだがインポートは影響されない!!

//Studentクラス,HoseiStudentクラスを使いたければインポートを定義する

public class StudentInformation extends SchoolInformation{

private long money=200;

private long oturi;

public StudentInformation(long money, long gakuhi){

        this.money=money;

        this.gakuhi=gakuhi;

}

public void zankin(){

        if(money>=gakuhi){

         oturi=money-gakuhi;

         System.out.println(“おつりは”+oturi+”円です”);

        }

        if(money<gakuhi){

         oturi=money-gakuhi;

     System.out.println(-oturi+”円足りません”);

        }

}

}

Tester10クラス

package lesson10.id2;

import lesson10.HoseiStudent;

import lesson10.Student;

import lesson10.id.SchoolInformation;

import lesson10.id.StudentInformation;

//インポート:他のクラスをインスタンスを生成することにより呼べる!!!当たり前!!

import java.util.Scanner;

public class Tester10 {

        public static void main(String[] args){

                Scanner stdIn=new Scanner(System.in);//mainメソッド

                System.out.print(“年齢は:”);

                int a=stdIn.nextInt();

     if(a>=18){ 

                 Student s=new Student(a);//インスタンス生成

                   if(s.university()==1){

                         //”  ”←重要!!! 

 HoseiStudent hs=new HoseiStudent(a,”12×3020″,”理工学部”);//インスタンス生成

                     hs.kyanpasu();

                     System.out.println(“あなたの年齢は”+hs.getAge()+”です”);

                     System.out.println(“あなたの学籍番号は”+hs.getNumber()+”です”);//継承利用

                     System.out.println(“あなたの学部は”+hs.getGakubuname()+”です”);

                    SchoolInformation  sci=new SchoolInformation();//インスタンス生成  

                    System.out.print(“年間授業料は”);

                    long z=sci.expense(hs);//重要!!HoseiStudentクラス型変数hsを引数とる

                    System.out.println(“年間授業料がわかったところで授業料を振り込みます。”);

                    System.out.print(“振り込む金額:”);

                    long m=stdIn.nextInt();

                    StudentInformation sti=new StudentInformation(m,z);//インスタンス生成

                    sti.zankin();

                    }

                 else{

                         System.out.println(“ここから先は法政大学の学生さんしか使えません!!”);

                         System.out.println(“あなたの年齢は”+s.getAge()+”です”);

                 }

     }//if(a>=18)         

         if(a<18){

                        //break使えない!!

                        System.out.println(“ここから先は法政大学の学生さんしか使えません!!”);

                        //System.out.println(“あなたの年齢は”+s.getAge()+”です”);sが使えない

                }

 }

}

実行結果

3のソースプログラムの実行結果を以下の図1に示す。

図1 実行結果

考察

今回のプログラムはクラスが5つあるが、呼び出される順としては、mainメソッドをもつTester10クラスである。このクラスは、

import lesson10.HoseiStudent;

import lesson10.Student;

import lesson10.id.SchoolInformation;

import lesson10.id.StudentInformation;

とHosei Studebtクラス、Studentクラス、SchoolInformationクラス、StudentInformationクラスをインポートしている。このように定義することによりパッケージlesson10.id2;のTester10クラスで他のパッケージのクラスが利用出来る。ただし、正しく使えるよう、Hosei Studebtクラス、Studentクラス、SchoolInformationクラス、StudentInformationクラスの4つクラスはpublicクラスとして宣言しなければならない。クラスでは、まず年齢を変数aにキーボードから入力する。そして、その入力した変数a、つまり年齢が18以上なら次に進め、18未満ならSystem.out.printlnで「ここから先は法政大学の学生さんしか使えません!!」を出力して終了する。今回は20と入力している為、18以上なので、Student s=new Student(a);と、年齢の変数aを引数としてStudentクラスのインスタンス生成してStudentクラスのコンストラクタを生成する。コンストラクタの中身を見てみるとthis.age=age;と書いてあるがthis.ageのageはフィールドで定義したクラス変数private int age;でageは仮引数で今回は、引数a、つまり20を仮引数のageに代入されている。ちなみに、this.ageのthisはこのクラスのインスタンス、つまり今回はStudent s=new Student(a);のsを指している。インスタンス生成が終わったらif文で s.university()とStudentクラスのuniversityインスタンスメソッドを呼び出している。このインスタンスメソッドの中身は、まず「あなたはどこの大学生ですか」「法政・・・1  明治・・・2   慶應・・・3   その他・・・4」「相当する大学の番号1~4を入力してください」とSystem.out.printlnで出力する。その後、変数xに1~4の値を入力する。今回、自分は法政大学生なので「1」を入力したが、2、3を入力した場合は、それぞれが、System.out.printlnで「あなたは明治大学の学生さんですね」「あなたは慶應大学の学生さんですね」を出力して、return xによって、Tester10クラスのuniversityインスタンスメソッドのs.university()==1の部分に戻り評価するが「1」ではないので、else文に行き 「ここから先は法政大学の学生さんしか使えません!!」「あなたの年齢は”+s.getAge()+”です」とSystem.out.printlnで出力する。ここで、先ほどコンストラクタで定義したインスタンス変数ageをインスタンスメソッドgetAge()を使って呼び出しているが理由はインスタンス変数ageがprivateで定義されていて、直接アクセスできないからだ。4を入力した場合は、キーボード入力を使って大学名を入力するが、今回は大学名ということで文字列を入力するので、スペースを含めた1行分の入力を文字列として読み込むstdIn.nextLine()を使用した。入力したのをフィールドで定義してあるprivate String name;のnameに代入する。それを、System.out.printlnで「あなたは”+name+”大学の学生さんですね」と出力する。+name+と出力しているのはmaneがこのクラスで定義されているからである。入力「1」に戻ってプログラムを見ていくと、HoseiStudent hs=new HoseiStudent(a,”12×3020″,”理工学部”);とHoseiStudentクラスのインスタンスを生成してコンストラクタを呼び出す。ここで、HoseiStudentクラスはStudentクラスから派生されている。それはpublic class HoseiStudent extends Studentをみるとextends Studentと書いてある箇所で分かる。派生とは、既存クラスのフィールドやメソッドなどの資産を継承した新しいクラスを作りだすこと。また、派生の際は、資産を継承するだけでなく、フィールドやメソッドを追加したり、上書きしたりすることも可能だ。

さて、コンストラクタの中身を見てみると

public HoseiStudent(int age,String number,String gakubuname){

           super(age);//派生利用 

           this.number=number;

           this.gakubuname=gakubuname;

   }

と定義されている。super(age);と書いてあるが、コンストラクタの先頭でsuper(・・・)を実行することにより、スパークラス、この場合Studentクラスのコンストラクタを呼び出せる。このsuper(・・・)は、同一クラス内の他のコンストラクタを呼び出すthis(・・・)と似ているが、1つコンストラクタの中で、superとthisの両方を呼び出すことは出来ない。

 また、プログラムを書いて分かったことがある。それは、Studentクラスでコンストラクタを定義するとこのクラスではsuper()を使って定義しなければならないということ。学籍番号を出すnameをString型にしたのは12x3020と学籍番号を入力した時にint型だとxの部分が出ずエラーが起きるからだ。インスタンスの生成、コンストラクタによる初期化が終わると、hs.kyanpasu()とHoseiStudentクラスのインスタンスメソッドkyanpasu()を呼び出し1~3の中から自分が所属する学部がある番号を選び、変数xにキーボードから入力する。入力するとif文で処理が行われ該当するキャンパス名がSystem.out.printlnによって出力される。終了すると、Tester10クラスに戻り年齢、学籍番号、学部をhs.getAge()、hs.getNumber()、hs.getGakubuname()によって出力する。ここでStudentクラスのインスタンスメソッドgetAge()はHoseiStudentのインスタンスhsでアクセス出来ているのかというと、先ほどもも述べた通りHoseiStudentクラスはStudentクラスから派生されているからだ。続いて、SchoolInformation  sci=new SchoolInformation();とSchoolInformationクラスのインスタンスを生成している。このクラスは今回定義されていない為、デフォルトコンストラクタが呼ばれる。その後、年間授業料を出すため、sci.expense(hs)とHoseiStudentクラス型変数hsを引数とるインスタンスメソッドを呼び出す。このメソッドをの中身を見ていくと、if文の評価する部分でHS.getGakubuname()と呼び出し、学部名をreturnで返して同じ学部名があれば授業料をSystem.out.printlnで出力してprotected long gakuhiに学費を代入している。Protectedとは派生したクラスでは使えるという修飾子である。つまり限定で公開できるということ。ちなみにprivateは非公開だ。このクラス、SchoolInformationクラスはパッケージlesson10,クラスStudent,HoseiStudentをインポートしている。従って、expenseインスタンスメソッドの引数の型がHoseiStudentと置けたのだ。Return gakuhiをしたらTester10クラスに戻り変数zに代入される。その後、授業料が分かったのでお金を振り込む。変数mにキーボードから支払う金額を入力する。それが終わると、年間授業料と振り込む金額が代入されている変数z,mを引数ととるStudentInformationクラスのインスタンスStudentInformation sti=new StudentInformation(m,z)を生成し、コンストラクタが呼び出される。SchoolInformationクラスのインスタンス変数gakuhiがStudentInformationクラスでエラーなく使われているのは、StudentInformationクラスはSchoolInformationクラスの派生クラスでインスタンス変数gakuhiがprivateではなくprotectedで定義されているからである。無事にコンストラクタによる初期化が終わると、sti.zankin();によって残金を出している。これでプログラムが終了する。

まとめ

 クラスの派生によって、既存クラスの資産を継承したクラスを簡単に作ることができる。派生元のクラスをスーパークラスと呼び、派生によって作られたクラスをサブクラスと呼ぶ。派生は、クラスに血縁関係を与える。コンストラクタの先頭では、super(・・・)によってスーパークラスのコンストラクタを呼び出せる。明示的に呼び出さなければ、スーパークラスの引数を受け取らないコンストラクタの呼び出しsuper()が、コンパイルによって自動的に挿入される。コンストラクタを1個も定義しないクラスには、super()のみを実行するデフォルトコンストラクタが、コンパイラによって自動的に定義される。スーパークラスが引数を受け取らないコンストラクタを持っていなければ、コンパイルエラーとなる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です