〜プログラミング2 Report#5〜


課題

講義資料オブジェクト指向プログラムJavaIの中のサンプルプログラムのポイントについて考察せよ。
各自オリジナルのサンプルプログラムのポイント(全ての講義内容を含んだ、1つのコード)を作成し考察せよ。 

それぞれのプログラム

☆クラスとオブジェクト
class CircleC {                                 // クラス
    double pai = 3.14;                          // データ
    double circle(int r) {                      // メソッド
        return pai * r * r;
    }
}
class Demo {                                    // クラス
    public static void main(String args[]) {    // メソッド
        double area;;
        CircleC obj;                            // オブジェクト
        obj  = new CircleC();
        area = obj.circle(10);
        System.out.println("area = " + area);
    }
}
〜実行結果〜
area = 314.0
〜考察〜

1.Class CircleCにおいてdouble型でpaiを定義する。
  circleメソッドは引数をrとして円の面積を求める計算を行う。

2.class Demoにおいてオブジェクトを作成する。→これをインスタンス化という。
  a.クラス内のメソッドを使うときは、そのクラスで定義したオブジェクトの
    どのメソッドであるのかピリオドをつけて指定する。
  b.CircleCのオブジェクトを作成し、circleメソッドの引数rに10を代入。

3.printlnで結果を出力。

☆オブジェクトを生成
class ObjSample {
    public static void main(String args[]) {
        Display obj = new Display();   // クラスDisplayのオブジェクトobj生成
        obj.Disp("Hello Java");        // オブジェクトobjのメソッドDispを呼ぶ
    }
}
class Display {                    // クラスDisplayの定義
    void Disp(String message) {      // メソッドDispの定義
        System.out.println(message);
    }
}
〜実行結果〜
Hello Java
〜考察〜

1.class ObjSampleにてclass Displayをインスタンス化する。
  a.Display obj = new Display();は
    Display obj;

    obj = new Display();と同じ意味を持つ。

2.class DisplayではDispメソッドにて引数messageをprintlnにて画面に出力させる。

3.class ObjSample内のobj.Disp("Hello Java");でDispメソッドに代入。

☆四則演算を各計算毎にクラス化している計算プログラム
class Comp4 {                         // クラスComp4を定義
    int add(int x, int y) {                    // メソッドadd(int x,int y)を定義
        return x + y;                            // x + y を返す
    }
    int substract(int x, int y) {              // メソッドsubstractを定義
        return x - y;                            // x - y を返す
    }
    int multiply(int x, int y) {               // メソッドmultiplyを定義
        return x * y;                            // x * y を返す
    }
    int divide(int x, int y) {                 // メソッドdivideを定義
        return x / y;                            // x / y を返す
    }
}
public class Keisan {
    public static void main(String args[]) {
        int a, b, wa, sa, seki, sho;
        Comp4 enzan = new Comp4();               // クラスComp4のオブジェクトenzan作成
        a = 20;
        b = 10;
        wa   = enzan.add(a, b);                  // オブジェクトenzanのadd(a,b)を実行
        sa   = enzan.substract(a, b);            // 同上のsubstract(a,b)を実行
        seki = enzan.multiply(a, b);             // 同上のmultiplyを実行
        sho  = enzan.divide(a, b);               // 同上のdivide(a,b)を実行
        System.out.println(a + " + " + b + " = " + wa);
        System.out.println(a + " - " + b + " = " + sa);
        System.out.println(a + " * " + b + " = " + seki);
        System.out.println(a + " / " + b + " = " + sho);
    }
}
〜実行結果〜
20 + 10 = 30
20 - 10 = 10
20 * 10 = 200
20 / 10 = 2
〜考察〜

1.class Comp4には4つのメソッドが含まれている。
  a.addメソッドは加算。引数xとyを加算しreturnで結果を返す。
  b.substractメソッドは減算。引数xからyを減算しreturnで結果を返す。
  c.multiplyメソッドは乗算。引数xとyを掛けてreturnで結果を返す。
  d.divideメソッドは除算。引数xをyで割ってreturnで結果を返す。

2.class KeisanではComp4 enzan = new comp4();
  でクラスComp4のオブジェクトenzanを作成し、
  a.a=20,b=10を定義し、class Comp4内の各メソッド内に代入。
  それぞれの結果をwa,sa,seki,shoに代入。

3.plintlnにてそれぞれの結果を出力。

☆ローカル変数とクラス変数
class Display {
    int n;                                     // クラス変数
        void Disp() {
        int i;                                   // ローカル変数
        for (i = 1; i <= n; i++)
            System.out.print(i + " ");
    }
}
class VarSample {
    public static void main(String args[]) {
        Display obj = new Display();             // クラスDisplayのオブジェクトobj生成
        obj.n = 10;                              // オブジェクトobjの変数nに10を代入
        obj.Disp();                              // オブジェクトobjのDisp()実行
    }
}
〜実行結果〜
1 2 3 4 5 6 7 8 9 10
〜考察〜

1.ローカル変数とは、メソッドの内部で宣言した変数のこと。

2.クラス変数とは、メソッドの外部で宣言した変数のこと。

3.Dispメソッドの外部で定義されたクラス変数nにはobjを介して違うクラスからも
  代入できる。

4.Dispメソッドの中身はfor文で1からnまで(n=10)i++し、printによって出力。

☆static変数(1)
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

☆static変数(2)
class Sum2 {
    static int total;                    // 値を共有させる
    Sum2() {                              // コンストラクタ(クラス名と同名)
        total = 0;                         // 0 クリア
    }
    void add(int x) {
        total += x;
    }
}

class SumSample2 {
    public static void main(String args[]) {
        Sum2 obj1 = new Sum2();              // クラスSumのオブジェクトobj1生成
        Sum2 obj2 = new Sum2();              // クラス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
〜考察〜

1.static変数は関数やブロック内で宣言された変数である。そのブロックが終了しても値を保持しているもの。
  静的変数とも呼ばれる。生成されたオブジェクトの個数や状態をそのブロック内に格納しておく変数として
  使うと便利である。グローバル変数のように、他の関数から使用することはできない。

2.二つのプログラムの違いはstatic変数を使っているかいないかの違いである。
  a.プログラム1はint型で変数totalを定義し、3行目でコンストラクタを作成。
    class SumSample{}の中で、クラスSumのオブジェクトobj1,obj2を生成し、obj1とobj2に数字を入れ計算する。

  b.変数totalがobj1とobj2で区別されているので、obj1とobj2の中に入れられた数字をそれぞれ計算して出力する。

  c.プログラム2はstatic int totalで値を共有させる変数totalを定義。
    その他は一つ目のプログラムと同じだが、int型変数obj1.totalとobj2.totalは同じ変数totalを
    指しているのでobj1とobj2で区別無く加算される。
☆コンストラクタ
class Sum {
    int total;
    Sum() {                              // コンストラクタ 引数無し
        total = 0;
    }
    Sum(int x) {                         // コンストラクタ 引数 x
        total = x;
    }
    void add(int x) {
        total += x;
    }
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
〜考察〜

1.コンストラクタはクラス名と同じ名前のメソッドのことである。
  a.コンストラクタはオブジェクトの初期化処理に利用できる。
  b.引数を受け取ることができるが、戻り値を返すことはできない。
  c.コンストラクタを直接呼び出すことはできない。常にnew演算子で呼び出さなければならない。

2.コンストラクタSumはオブジェクトを作成したときに引数があればtotalにその値を代入し、無ければ0をtotalに代入する。

3.sum1とsum2の結果が違うのはsum2にはオブジェクトを作成したときに引数100がtotalに代入されているからである。

☆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
〜考察〜

1.staticイニシャライズは、クラスが呼ばれた(ロードされた)ときに自動的に実行される。
  a.コンストラクタよりも早く処理がしたい場合や、一度だけ処理を行いたい場合などに用いる。

2.プログラムでもDispコンストラクタの前にstaticイニシャライズが記述されている。

3.Dispをインスタンス化した際に最初のコンストラクタを処理する前にstaticイニシャライズが実行される。
  a.しかし、次のobj2を作成したときに実行されてないことが分かる。
    これはstaticイニシャライズが一回しか実行しないことを示す。

4.このプログラムではstaticイニシャライズでinitializeをDispコンストラクタにて
  constructを文字列出力するものである。
☆メソッドのオーバーロード
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)を実行
    }
}
〜実行結果〜
Nothing
1
3
〜考察〜

1.オーバーロードとは同じメソッド名で、引数リストの異なるメソッドを同時に定義すること。
 a.このプログラムでは3つのDisppメソッドがオーバーロードの関係にある。
  b.引数なしの場合Nothingが文字列出力される。
 c.引数が1つ指定されたらその引数を出力する。
 d.引数が2つ指定されたらその2つの引数を加算し、結果を出力する。

2.引数の組まで同じにするとコンパイルエラーになる。
  a.メソッド名も引数の型の組も同じにすると、呼び出し時にどちらを実行してよいか分からなくなるからである。

3.オーバーロードされたメソッドは別のメソッドとして区別されるので、
  戻り値型や修飾子などは任意のものが指定できる。
☆アクセス制御
class keisan {
    static 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
〜考察〜

1.クラス、メンバ変数(フィールド)、メソッド、コンストラクタには修飾子を指定できる。
  a.それぞれに指定できる修飾子は異なり、言語仕様として定義されている。

2.アクセス制御する修飾子

  public:全てのオブジェクトの全てのメソッドからアクセス可能

  private:定義されたクラス内のメソッドからだけアクセス可能

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

3.プログラムの中身はkeisanメソッドを呼び出してkingakuに単価1000×引数3(1.0+rate0.05)を代入。
 a.tankaとkazuとkingakuを出力する。
  b.23行目はrateがprivateで定義されているため参照できないことからコメントアウトされている。
☆オリジナルプログラム
class Report5 { // クラスReport5を定義
    int n; //クラス変数n
    int add(int x, int y) { // メソッドadd(int x,int y)を定義
        return x + y + n; // x + y + n を返す
    }
    int substract(int x, int y) { // メソッドsubstractを定義
        return x - y - n; // x - y - n を返す
    }
    int multiply(int x, int y) { // メソッドmultiplyを定義
        return x * y * n; // x * y * nを返す
    }
    int divide(int x, int y) { // メソッドdivideを定義
        return x / y / n; // x / y / n を返す
    }
}

class Display {
    void Disp(String message) { // メソッドDispの定義
        System.out.println(message);
    }
}

public class Keisan {
    public static void main(String args[]) {
        int a, b, wa, sa, seki, sho;
        Report5 enzan = new Report5(); // クラスReport5のオブジェクトenzan作成
        a = 400;
        b = 20;
        enzan.n = 10; //クラスReport5のクラス変数nに10を代入
        wa = enzan.add(a,b); // オブジェクトenzanのadd(a,b)を実行
        sa = enzan.substract(a,b); // 同上のsubstract(a,b)を実行
        seki = enzan.multiply(a,b); // 同上のmultiply(a,b)を実行
        sho = enzan.divide(a, b); // 同上のdivide(a,b)を実行
        System.out.println(a + " + " + b + " + n " + " = " + wa);
        System.out.println(a + " - " + b + " - n " + " = " + sa);
        System.out.println(a + " * " + b + " * n " + " = " + seki);
        System.out.println(a + " / " + b + " / n " + " = " + sho);
        Display obj = new Display(); // クラスDisplayのオブジェクトobj生成
        obj.Disp("↑n = 10に設定"); // オブジェクトobjのメソッドDispを呼ぶ
    }
}
〜実行結果〜
400 + 20 + n  = 430
400 - 20 - n  = 370
400 * 20 * n  = 80000
400 / 20 / n  = 2
↑n = 10に設定
〜考察〜

1.四則演算を各計算毎にクラス化している計算プログラムにクラス変数を追加してみた。
  a.またDisplayメソッドを定義し、objを作成して文字列を出力してみた。

2.クラスKeisanのなかでオブジェクトenzanを作成後にReport5のクラス変数nに10を代入している。
  a.nが計算に入ったので実行結果がサンプルプログラムとは全く違うものになった。
  b.今回はint型で指定しているためちゃんと割り切れる数値を選んだ。

3.System.out.printlnの中で最初は
  (a + " + " + b + " + " + " + " n " + " = " + wa);
  としていたが、n=0と定義する必要があり面倒だったので(しかも実行結果にはnでなく0と出力された)
  現在のような" + n "として中に入れることにした。

反省と感想

要素を取り入れながらプログラミングを組むのはかなり難しかった。
まだまだよく分かっていないだろうから、教科書をじっくり読んでプログラミングを続けようと思います。

参考資料

・翔泳社 出版 JOSEPH O'NEIL 著 トップスタジオ 訳 独習Java 第3版

ひとつ前のページに戻る

たいきのぺぇじ☆とっぷに戻る
プログラミング2 Wikiページに戻る