■Report6

■課題

  ●11/15付講義資料と今回の講義資料中のサンプルプログラムについて考察せよ。
   講義資料サンプルプログラム考察については、static変数以降とする。

◎static変数

class Sum {
    int total;
    Sum() {                              // コンストラクタ(クラス名と同名)
      total = 0;                         // 0 クリア
    }
    void add(int x) {
      total += x;
    }
  }
  
  class SumSample {
    public static void main(String args[]) {
      Sum obj1 = new Sum();              // クラスSumのオブジェクトobj1生成
      Sum obj2 = new Sum();              // クラスSumのオブジェクトobj2生成
      obj1.add(10);
      obj1.add(20);
      obj2.add(30);
      obj2.add(40);
      System.out.println("obj1.total = " + obj1.total);
      System.out.println("obj2.total = " + obj2.total);
    }
  }  
  
 *実行結果*
  
  obj1.total = 30
 obj2.total = 70
  class Sum {
    static int total;                    // 値を共有させる
    Sum() {                              // コンストラクタ(クラス名と同名)
      total = 0;                         // 0 クリア
    }
    void add(int x) {
      total += x;
    }
  }
  
  class SumSample {
    public static void main(String args[]) {
      Sum obj1 = new Sum();              // クラスSumのオブジェクトobj1生成
      Sum obj2 = new Sum();              // クラスSumのオブジェクトobj2生成
      obj1.add(10);
      obj1.add(20);
      obj2.add(30);
      obj2.add(40);
      System.out.println("obj1.total = " + obj1.total);
      System.out.println("obj2.total = " + obj2.total);
    }
  }  

※実行結果
  obj1.total = 100
  obj2.total = 100

〜考察〜

  ・static変数は関数やブロック内で宣言された変数である。静的変数ともよばれる。
  ・上のふたつのプログラムのプログラムはほとんど一緒で、整数型の変数totalが静的であるかないかのちがいである。
  ・はじめのプログラムはobj1とobj2の値が別で、中に入れられた数字をそれぞれ計算して出力する。
  ・2つ目のプログラムはobj1とobj2の値が共有されていて、区別無く加算される。

◎コンストラクタ   

 class Sum {
    int total;
    Sum() {                              // コンストラクタ 引数無し
      total = 0;
    }
    Sum(int x) {                         // コンストラクタ 引数 x
      total = x;
    }
    void add(int x) {
      total += x;
    }
  }
  
  class ConstrcSample {
    public static void main(String args[]) {
      Sum obj1 = new Sum();              // クラスSumのオブジェクトobj1生成
      obj1.add(10);
      obj1.add(20);
      System.out.println("sum1 = " + obj1.total);
      Sum obj2 = new Sum(100);           // クラスSumのオブジェクトobj2生成
      obj2.add(10);
      obj2.add(20);
      System.out.println("sum2 = " + obj2.total);
    }
  }  

※実行結果
  sum1 = 30
  sum2 = 130

〜考察〜 

  ・コンストラクタはクラス名と同じ名前のメソッドのことである。(名前はクラス名と同じでなければならない。)
  ・コンストラクタはオブジェクトの初期化処理に利用できる。
  ・引数をうけとることができるが、戻り値を返すことはできない。
  ・コンストラクタを直接呼び出すことはできず、常にnew演算子で呼び出さなければならない。
  ・そのクラスのオブジェクトが作成されたときに、定義しておいたコンストラクタ内の処理が自動的に行われる。

 

◎staticイニシャライズ

class Disp {
    static {                             // static イニシャライズ
        System.out.println("initialize");
    }
    Disp() {                             // コンストラクタ
        System.out.println("construct");
    }
  }
  
  class StaticSample {
    public static void main(String args[]) {
      Disp obj1 = new Disp();            // オブジェクト生成時にコンストラクタを処理
      Disp obj2 = new Disp();            // オブジェクト生成時にコンストラクタを処理
    }
  }  
  
  *実行結果*
  
  initialize
 construct
 construct

〜考察〜

  ・イニシャライズとは、コンストラクタの前に記述するメソッドのことで、
   コンストラクタが呼び出される前に実行される。
  ・staticイニシャライズはコンストラクタより早く処理したいときや、一度だけ処理を行いたい場合などに用いる。
  ・ 実行結果よりobj1のコンストラクタよりも早く実行されている。
    また、1度だけしか処理されないのでobj2のときは行われていないことが分かる。

◎メソッドのオーバーロード

class Display {
    void Disp() {                          // メソッド Disp 引数なし
        System.out.println("Nothing");
    }
    void Disp(int x) {                     // メソッド Disp 引数 x
        System.out.println(x);
    }
    void Disp(int x, int y) {              // メソッド Disp 引数 x, y
        System.out.println(x + y);
    }
  }
  
  class OvldSample {
    public static void main(String args[]) {
      Display obj = new Display();    // クラスDisplayのオブジェクトobj生成
      obj.Disp();                     // オブジェクトobjのDisp()を実行
      obj.Disp(1);                    // オブジェクトobjのDisp(1)を実行
      obj.Disp(1, 2);                 // オブジェクトobjのDisp(1,2)を実行
    }
  }  

※実行結果
  Noting
  1
  3

〜考察〜

  ・メソッドのオーバーロードとは、同じ名前が複数あること。
  ・メソッド名が同じでも、その引数の個数や引数のデータ型を異なるものにすることで複数のメソッドを定義できる。
  ・名前とシグネチャが同一であるメソッドがクラス内に2つあると、
   区別があいまいになりエラーメッセージが表示される。
  ・メソッドのオーバーロードを使うと、基本的な用途が同じであるメソッド群に同一の名前を付けることができる。
  ・メソッドに引き渡すデータ型ごとに違うメソッド名を覚えておかなくても、1つのメソッド名で用が足りるので、便利   である。
  ・メソッドのオーバーロードには、既定のパラメータ値を簡単に用意できるというメリットもある。
  ・あるメソッドに省略可能なメソッドがある場合、省略されたパラメータには既定値を使うようにできる。

◎アクセス制御

  class keisan {
    atatic int tanka;
    private float rate;                    // private変数rateの宣言
    keisan() {                             // コンストラクタ
        tanka = 1000;
        rate  = 0.05f;
    }
    int keisan(int kazu) {
      int kingaku;
      kingaku = (int)(tanka * kazu * (1.0 + rate));
      return kingaku;
    }
  }
  
  class PrvSample {
    public static void main(String args[]) {
      keisan obj1 = new keisan();
      int kazu = 3;
      int kingaku = obj1.keisan(kazu);
      System.out.println("tanka   = " + obj1.tanka);
      System.out.println("kazu    = " + kazu);
      System.out.println("kingaku = " + kingaku);
  //  System.out.println("rate = " + obj1.rate);  //private変数のため参照不可
    }
  }  

※実行結果
  tanka   = 1000
  kazu    = 3
  kingaku = 3150

〜考察〜

  ●アクセス制御する修飾子

public
全てのオブジェクトの全てのメソッドからアクセス可能
private
定義されたクラス内のメソッドからだけアクセス可能
protected

定義されたクラス内のメソッド、そのクラスから派生したサブクラス、
同一パッケージ内のクラスからアクセス可能

  ・上記プログラム内の "//" を消すと、エラーが起こる。これは、private修飾子のついた変数rateを、
   rateの定義されたクラスとは別のクラスの中で参照しようとしたためである。

◎継承

class Display {                                 // スーパークラス Display
    void Disp() {                               // メソッド
        System.out.println("Hello!");
    }
}

class Succeed extends Display {                 // スーパークラス Displayを継承したサブクラス Succeed
    public static void main(String args[]) {    // メソッド
        Succeed obj = new Succeed();            // オブジェクト生成
        obj.Disp();                             // スーパークラスから継承したメソッドを利用
    }
}

※実行結果
    Hello!

〜考察〜

  ・継承(extends)とは、あるクラスの状態と動作を、新たな別のクラスが受け継ぐ事である
  ・元になるクラスを「スーパークラス」
   それを継承する新しいクラスを「サブクラス」と呼ぶ
  ・上記のプログラムでは、DisplayがスーパークラスでSucceedがサブクラス
  ・サブクラスSucceedにHelloは無いが、スーパークラスのDisplayから継承して表示している
  ・1つのクラスは複数のサブクラスを持つことができるが、直接的なスーパークラスは1つしか
   持つことができない

◎メソッドのオーバーライド

class Display {                                 // スーパークラス Display
    void Disp() {                               // メソッド
        System.out.println("Hello!");
    }
}

class Override extends Display {                // サブクラス Override
    void Disp() {                               // メソッドのオーバーライド
        System.out.println("Hello! Java!!");
    }
    public static void main(String args[]) {    // メソッド
        Override obj = new Override();          // オブジェクト生成
        obj.Disp();                             // メソッド Disp 実行
    }
}

※実行結果
    Hello! Java!!
	

〜考察〜

  ・スーパークラスを継承した場合でも、サブクラス内でスーパークラスと同じ名前のメソッドを
   定義し直すことができる
  ・同じメソッドでも、後に定義された方が優先される
  ・上記プログラムの場合、 サブクラスOverrideにスーパークラスDisplayと同じメソッド
   Dispをつくりオーバーライドさせている

◎super

class Display {                                 // スーパークラス Display
    void Disp() {                               // メソッド
        System.out.println("Hello!");
    }
}

class SuperSample extends Display {             // サブクラス SuperSample
    void Disp() {                               // メソッドのオーバーライド
        super.Disp();                           // スーパークラスの Disp 実行
        System.out.println("Hello! Java!!");
    }
    public static void main(String args[]) {    // メソッド
        SuperSample obj = new SuperSample();    // オブジェクト生成
        obj.Disp();                             // サブクラスの Disp 実行
    }
}

※実行結果
    Hello!
    Hello! Java!!

〜考察〜

  ・superは、オーバーライドした定義の内側からスーパークラスのメソッドを呼び出す
  ・上記プログラムでは、まずDisplayを継承したサブクラスSuperSampleは
   メソッドDispを定義してオーバーライド
  ・サブクラスのメソッドDispでsuperをつかい、スーパークラスのメソッドDispを呼び出せるようにする
  ・その後、サブクラスSuperSampleをオブジェクト化して、メソッドDispを実行する
  ・結果、サブクラスのDispがまず実行され、その内部でスーパークラスのDispが呼び出される

◎this

class Keisan {                                  // スーパークラス Keisan
    int x = 100;
    void add(int x, int y) {                    // メソッド
        int w1 = x + y;
        int w2 = this.x + y;
        System.out.println("w1 = " + w1 + "  w2 = " + w2);
    }
}

class ThisSample1 extends Display {             // サブクラス ThisSample1
    public static void main(String args[]) {    // メソッド
        ThisSample1 obj = new ThisSample1();    // オブジェクト生成
        obj.add(10, 20);                        // add 実行
    }
}

※実行結果
    w1 = 30  w2 = 120
class Keisan {
    void Keisan(int x, int y) {                 // 引数が二つのコンストラクタ
        System.out.println("Keisan = " + (x * y));
    }
    void Keisan(int x) {                        // 引数が一つのコンストラクタ
        this(x, 1);                             // Keisan(x, 1)と同じ
    }
}

class ThisSample2 extends Display {             // サブクラス ThisSample2
    public static void main(String args[]) {    // メソッド
        Keisan obj1 = new Keisan(200, 5);       // 引数が二つのコンストラクタ実行
        Keisan obj2 = new Keisan(200);          // 引数が一つのコンストラクタ実行
    }
}

※実行結果
    Keisan = 1000
    Keisan = 200
	

〜考察〜

  ・メソッド内にグローバルな変数と同じ名前の変数を作ると、メソッド内ではメソッド内の変数
   (ローカル変数)の方が優先される。 メソッド内からメソッド外の変数(グローバル変数)にアクセス
   する時には、"this"を使う。 "this"はカレントクラス(今いる場所のクラス)を表し、
   変数につけることでクラス内、メソッド外で宣言された変数にアクセスできる。

◎abstract

public abstract class PreDefine {               // 抽象クラス PreDefine
    public abstract int add(int x, int y);      // 抽象メソッド add
    public int sub(int x, int y) {              // メソッド sub
        return x - y;
    }
}

class AbstractSample extends PreDefine {        // 抽象クラス PreDefine の継承
    public int add(int x, int y) {              // メソッドの内容を具体的に定義
        return x + y;
    }

    public static void main(String args[]) {    // メソッド
        AbstractSample obj = new AbstractSample();
        System.out.println("add = " + obj.add(100, 80));
        System.out.println("sub = " + obj.sub(100, 80));
    }
}

※実行結果
    add = 180
    sub = 20

〜考察〜

  ・クラス、メソッド宣言時に付けて、抽象クラス、抽象メソッドを宣言する。
  ・抽象クラスはオブジェクトを生成することが出来ず、抽象メソッドと抽象メソッドでないメソッドを生成できる。
  ・メソッド自体を抽象化することもでき、このような抽象メソッドの宣言は、外枠だけで中身はない。

◎interface

public interface PreDefine {                    // インタフェース PreDefine
    int add(int x, int y);                      // 抽象メソッド add
    int sub(int x, int y);                      // 抽象メソッド sub
}

class InterfaceSample implements PreDefine {     // PreDefine のインプリメント
    public int add(int x, int y) {              // メソッドの内容を具体的に定義
        return x + y;
    }
    public int sub(int x, int y) {              // メソッドの内容を具体的に定義
        return x + y;
    }

    public static void main(String args[]) {    // メソッド
        InterfaceSample obj = new InterfaceSample();
        System.out.println("add = " + obj.add(100, 80));
        System.out.println("sub = " + obj.sub(100, 80));
    }
}

※実行結果
    add = 180
    sub = 20

〜考察〜

  ・インターフェイスとはクラスの形式を定義する定数とメソッド宣言を集めたもののことをいう。
  ・インターフェイスにはメソッドはない。
  ・基本的にインターフェイスはクラスの役割を示すもので、その具体的な方法を決めるものではない。

■感想・反省

  ・ものすご〜く提出遅れちゃいました。すいません m(__)m
   それぞれの特徴などは理解したつもりですが、言葉にするのに苦労しました。
   とにかく目が疲れました。ドライアイってやつですかね〜

■参考文献

  「独習 JAVA第2版」   ジョゼフ・オニール 著