講義メモ p.158「簡単なクラスを定義しよう(生成と参照)」から p.157 簡単なクラスを定義しよう(インスタンス変数の複数定義・生成)【再掲載】 ・「int x, y;」というように、同じ型の変数をまとめて宣言できる ・インスタンス名も同様で「クラス名 インスタンス名①, インスタンス名②, …」と記述できる ・なお、インスタンスの生成もまとめて行える(「int x = 1, y = 2;」と同様に) ・書式例: クラス名 インスタンス名① = new クラス名(), インスタンス名② = new クラス名(), …; p.158 簡単なクラスを定義しよう(生成と参照) ・「クラス名 インスタンス名」で宣言したインスタンス名(オブジェクト名)にはオブジェクトそのものが格納されるわけではない。 ・p.40下の参照型の図の通り、インスタンス名にはオブジェクトを示す参照(オブジェクトの位置情報)が与えられる ・よって、異なる2つのインスタンス名に1つのオブジェクトの参照を格納でき、同じオブジェクトを指すことができる(p.159上の図参照) ・つまり、こうすることで、オブジェクトに別名をつけることが可能 ・これは多くのテクニックに活用されている アレンジ演習:p.158 simpleclass03.cs ・021行目の後で、新たにMyClassオブジェクトを生成して変数bに与え、b.xに1000を代入すると、a.xはどうなるか確認しよう 作成例 //アレンジ演習:p.158 simpleclass03.cs using System; class MyClass { //クラスの定義 public int x; //インスタンス変数の定義 } class simpleclass03 { //実行用クラス public static void Main() { //実行用メソッド MyClass a, b; //クラス型の2変数の宣言 a = new MyClass(); //オブジェクトを生成して変数aで参照する a.x = 10; //変数a経由でインスタンス変数xに代入 b = a; //変数aの参照を変数bに代入する(同じオブジェクトへの参照になる)) Console.WriteLine("b.x = {0}", b.x); //a.xと同じインスタンス変数なので10 b.x = 100; //変数b経由でインスタンス変数xに代入 Console.WriteLine("a.x = {0}", a.x); //b.xと同じインスタンス変数なので100 //【以下追加】 b = new MyClass(); //オブジェクトを新たに生成して変数bで参照する b.x = 1000; //変数b経由でインスタンス変数xに代入 Console.WriteLine("a.x = {0}", a.x); //b.xとは異なるインスタンス変数なので100のまま } } p.159 簡単なクラスを定義しよう(実行用クラスとインスタンス変数) ・Mainメソッドを含む実行用クラスに、インスタンス変数を定義することが可能 ・実行用クラスのインスタンスを生成すると、その中にあるインスタンス変数にアクセスできる ・詳しい仕組みはp.202「静的メソッド」にて  ※チームルールによっては、実行用クラスに、インスタンス変数を定義することは非推奨の場合もある p.160 メソッドを定義しよう ・Mainメソッドのような処理(振る舞い)の記述を、実行用ではないクラスにも記述できる ・メソッドは0個以上の情報を得て、なにか処理を行い、0または1個の情報を返すことができる ・例: Addメソッドに1と2を渡すと、加算処理が動作して、3を返す ・メソッドの定義書式: アクセス修飾子 戻り値型 メソッド名(引数型 引数名, …){処理内容} ・アクセス修飾子:メソッドをクラスの外から呼び出す場合はpublicを指定(よって、Mainメソッドはpublic)  何も指定しないか、privateを指定すると、内部用になる(クラス内の別のメソッドからは利用可能) ・戻り値型(復帰型)は返す情報のデータ型を記述する。なお、ない場合は voidを指定する(よって、Mainメソッドは基本的にvoid) ・引数:メソッドに渡す情報で、0個以上いくつでも記述でき「データ型 引数名」をカンマつなぎする ・なお、0個の場合はカッコのみ記述する(よって、MainメソッドはMain()が基本) ・処理内容では、戻り値型が指定してある時は「return 値や式;」が必須になり、分岐などを含むときは、どの分岐になっても必ずreturnが実行される必要がある。 ・外部からメソッドを実行するには、インスタンス変数と同様に「オブジェクト名.メソッド名(…)」とする ・例:  class Monster { //クラスの定義   public int hp; //インスタンス変数の定義   public void showhp() { Console.WriteLine("HPは{0}", hp); } //メソッドの定義  }  :  class Game { //実行用クラス   public static void Main() { //実行用の特別なメソッド    Monster slalin = new Monster(); //Monsterオブジェクトを生成してスラリンとする    slalin.hp = 10; //スラリンのインスタンス変数hpに代入    slalin.showhp(); //スラリンのメソッドshowhp()を実行   }  } ・なお、returnの直後は(if-else構文等の場合を除き)実行されないので何かを記述するとエラーになる アレンジ演習:p.161 method01.cs ・2引数を受け取り、差を返すpublic int Sub(int x, int y)メソッドを追記しよう ・Mainメソッドに上記を呼び出す記述を追記しよう ・どちらも、できるだけシンプルにすること 作成例 //アレンジ演習:p.161 method01.cs using System; class MyClass { //クラスの定義 public int Add(int x, int y) { //int型の2引数を受け取ってint型の値を返すAddメソッドの定義 int z; //計算用の変数(※メソッドの中で定義しているのでメソッド内のみ有効なローカル変数) z = x + y; return z; //和を返す } public int Sub(int x, int y) { //int型の2引数を受け取ってint型の値を返すSubメソッドの定義 return (x > y) ? x - y : y - x; //差を返す } } class method01 { public static void Main() { //実行用の特殊クラス(この1行下が開始行) MyClass a = new MyClass(); //MyClassオブジェクトを生成し変数aで扱う int sum; //戻り値用の変数(※ローカル変数) sum = a.Add(100, 200); //変数a経由でAddメソッドを呼んで2引数を渡し、結果を変数sumで受け取る Console.WriteLine("sum = {0}", sum); //受け取った結果を表示 //変数a経由でSubメソッドを呼んで2引数を渡し、受け取った結果を表示 Console.WriteLine("sub = {0}", a.Sub(50, 200)); } } p.161 メソッドを定義しよう:インスタンスメソッド ・通常のメソッドはインスタンスに含まれており、newなどでインスタンスオブジェクトを生成することにより利用可能になる ・このようなメソッドをインスタンスメソッドという ・なお、Mainメソッド、Console.WriteLineメソッドなどは特殊型でインスタンスメソッドではない ・インスタンスメソッドは自分の属するオブジェクトにあるインスタンス変数を扱える ・例:  class Monster { //部品クラスの定義   public int hp; //インスタンス変数の定義   public void showhp() { //インスタンスメソッドの定義    Console.WriteLine("HPは{0}", hp); //hpを表示   }  }  :  class Game { //実行用クラス   public static void Main() { //実行用の特別なメソッド    Monster slalin = new Monster(); //Monsterオブジェクトを生成してスラリンとする    slalin.hp = 10; //スラリンのインスタンス変数hpに代入    slalin.showhp(); //スラリンのインスタンスメソッドshowhp()を実行    Monster hoimin = new Monster(); //Monsterオブジェクトを生成してホイミンとする    hoimin.hp = 20; //ホイミンのインスタンス変数hpに代入    hoimin.showhp(); //ホイミンのインスタンスメソッドshowhp()を実行   }  } アレンジ演習:p.163 bmiclass.cs ・身長や体重に0以下の値が入力されたら、先に進まずに再入力させるようにしよう 作成例 //アレンジ演習:p.163 bmiclass.cs using System; class BMI { //部品クラス private double blm; //身長(m単位):内部計算用のインスタンス変数なのでprivate public double Calc(double bl, double bw) { //身長(cm)と体重(kg)を受け取ってBMIを返すインスタンスメソッド blm = bl / 100.0; //身長(cm)を身長(m)に換算 return bw / Math.Pow(blm, 2.0); //体重を身長(m)の自乗で割ってBMIを得て返す } } class bmiclass { //実行用クラス public static void Main() { //実行用の特別メソッド string strBl, strBw; //入力用のローカル変数 double blcm, bwkg; //実数変換用のローカル変数 do { //入力ループ① Console.Write("身長(cm)---"); strBl = Console.ReadLine(); blcm = Double.Parse(strBl); //実数変換 } while (blcm <= 0); //0以下が入力されていたら繰返す do { //入力ループ② Console.Write("体重(kg)---"); strBw = Console.ReadLine(); bwkg = Double.Parse(strBw); //実数変換 } while (bwkg <= 0); //0以下が入力されていたら繰返す BMI bmi = new BMI(); //部品クラスのインスタンスオブジェクトを生成 Console.WriteLine("BMIは{0:#.##}です", bmi.Calc(blcm, bwkg)); //BMIを得て小数点以下2桁で表示 } } アレンジ演習:p.165 noreturnvalue.cs ・記述されている5つの「return」が全て不要であることを確認しよう ※「return」が常に不要という意味ではなく、メソッドの途中で呼び出し元に戻りたい場合に利用可能 ※ このプログラムの5つの「return」はメソッドの末尾や、メソッドの末尾に向かう位置にあるので不要 作成例 //アレンジ演習:p.165 noreturnvalue.cs using System; class Kakeibo { //部品クラス「家計簿」 private int total = 0; //内部処理用のprivateなインスタンス変数(残高) public void nyukin(int en) { //入金処理のインスタンスメソッド total += en; //引数で得た入金額を残高に足し込む Console.WriteLine("{0}円を入金しました", en); } public void shishutsu(int en) { //支出処理のインスタンスメソッド if (total < en) { //引数で得た支出金額より残高が小さい? Console.WriteLine("{0}円も支出できません", en); } else { //支出可能? total -= en; //引数で得た支出金額を残高から差し引く Console.WriteLine("{0}円を支出しました", en); } } public void gettotal() { //残高を得るインスタンスメソッド if (total == 0) { //残高なし? Console.WriteLine("残高はありません"); } else { Console.WriteLine("残高は{0}円です", total); } } } class noreturnvalue { //実行用のクラス public static void Main() { //実行用の特別なメソッド Kakeibo k = new Kakeibo(); //家計簿クラスのインスタンスを生成 k.gettotal(); //残高を得る(表示) k.nyukin(1000); //入金処理 k.gettotal(); //残高を得る(表示) k.nyukin(2000); //入金処理 k.gettotal(); //残高を得る(表示) k.shishutsu(500); //支出処理 k.gettotal(); //残高を得る(表示) k.shishutsu(10000); //支出処理 k.gettotal(); //残高を得る(表示) } } p.167 コンストラクタ ・全てのクラスがあらかじめ持っている特別なメソッド ・プログラマが必要に応じて記述することが可能で、そうでなければ自動的に中身が空のものが用意される ・これをデフォルトコンストラクタという ・よって、記述は任意 ・メソッドだが、メソッド名はなく、戻り値型もなく、public固定 ・コンストラクタはオブジェクトの生成時に自動的に呼び出されるもので、プログラマが任意に呼ぶことはできない ・よって、オブジェクトの生成時に行いたいことを記述するために用いる  例:インスタンス変数の初期化、リソースなどの準備処理 等 ・定義書式①: public クラス名() {処理内容} ・システム側で必ず実行されるので、実行漏れを防ぎたい初期化処理などを記述すると良い  例:モンスターの初期HP、MPを生成時に乱数で決めたい アレンジ演習:p.167 construct01.cs ・027行目の下で「MyClass md;」を実行すると、コンストラクタが動作するかどうか確認しよう  ⇒ 宣言のみでは動作しない ・また「MyClass md = new MyClass();」を実行すると、コンストラクタが動作するかどうか確認しよう  ⇒ オブジェクトを生成するとした数だけ動作する 作成例 //p.167 construct01.cs using System; class MyClass { //部品クラス int x; //インスタンス変数(private扱い) public void showx() { //インスタンスメソッド Console.WriteLine("x = " + x); //インスタンス変数を利用 } public MyClass() { //コンストラクタ x = 10; //インスタンス変数を利用 Console.WriteLine("xに10を代入しました"); } } class construct01 { public static void Main() { MyClass mc = new MyClass(); //ここでコンストラクタが動作 mc.showx(); //インスタンスメソッドを呼ぶ MyClass md = new MyClass(); //【追加】ここでもコンストラクタが動作 } } p.167 コンストラクタ:コンストラクタの引数 ・メソッドと同様にコンストラクタにも引数が指定できる ・引数を指定したコンストラクタを呼び出すには、newにおいてカッコ内に引数型と引数を記述する ・定義書式②: public クラス名(引数型 引数名, …) {処理内容}  例: public Slime(int h, int p) { hp = h; mp = p; } ・呼び出し法: new クラス名(値や式, …); 提出:アレンジ演習:p.167 construct01.cs 次回予告:「p.168 コンストラクタ:コンストラクタのオーバーロード」から