講義メモ ・p.160「メソッドを定義しよう」から p.160 メソッドを定義しよう ・実行用で特別な性質を持つのがMainメソッド(非インスタンス(静的)メソッド) ・とは異なる通常のメソッドをプログラマが記述できる ・通常のメソッドはクラスに所属するのでインスタンスメソッドといい、インスタンスの持つデータを扱うのに便利 ・例: MonsterクラスにHoimiメソッドとデータメンバhp、mpを定義し、インスタンスRimuruをnewsすると、「Rimuru.Hoimi()」を実行する事で、Rimuru.mpを減らし、Rimuru.hpを増やせる ・メソッドは値を0または1個返すことができる ・0個返すメソッド=何も返さないメソッドには戻り値型(返却値型)としてvoidを指定する ・1個返すメソッドには戻り値型を指定する。また、内部に1つ以上の「return ●」を記述する ・例:整数の和を返すメソッドは戻り値型も整数 ・メソッドのカッコ内には引数群を0個以上記述できる。これをパタメータのリストともいう ・引数はメソッドの呼び出し時に与えたいデータで「型 引数名」でカンマ繋で記述する ・例: int add(int a, int b){ int c = a + b; return c; } //整数2値の和を返すメソッド p.161 method01.cs //p.161 method01.cs using System; class MyClass { //method01クラスで用いられるクラス public int Add(int x, int y) { //2つの整数の引数を受け取って整数和を返すメソッド int z; //メソッド内でのみ用いる変数(ローカル変数) z = x + y; //2つの整数の引数の和を代入 return z; //変数zの値を返す } } class method01 { public static void Main() { MyClass a = new MyClass(); //利用したいクラスのインスタンスを生成 int sum; //合計用の変数(ローカル変数) sum = a.Add(100, 200); //インスタンスにあるメソッドに2整数を渡して呼び、結果を変数に代入 Console.WriteLine("sum = {0}", sum); //変数の値(合計値)を表示 } } アレンジ演習:p.161 method01.cs ・MyClassクラスにint型のインスタンス変数xを追加する ・そして、AddメソッドをAdd(int a)に変更し、引数の値とxの値の和を返すようにしよう ・Mainメソッドで、インスタンス変数xに適当な値を与えてから、Addメソッドを呼びだすこと。 作成例 //アレンジ演習:p.161 method01.cs using System; class MyClass { //method01クラスで用いられるクラス public int x; //【追加】インスタンス変数 public int Add(int y) { //【変更】整数の引数を受け取ってxとの和を返すメソッド return x + y; //インスタンス変数xと引数yの和を返す } } class method01 { public static void Main() { MyClass a = new MyClass(); //利用したいクラスのインスタンスを生成 Console.Write("加算値:"); a.x = int.Parse(Console.ReadLine()); //インスタンス変数の値を代入 Console.WriteLine("100に加えると{0}", a.Add(100)); //合計値を表示 Console.WriteLine("200に加えると{0}", a.Add(200)); //合計値を表示 Console.WriteLine("300に加えると{0}", a.Add(300)); //合計値を表示 } } p.163(実引数と仮引数) ・メソッドの定義における引数を仮引数ともいい、メソッドの中でのみ変数と同様に利用できる ・メソッドの呼び出しにおける引数を実引数ともいい、値や式(変数)を指定できる ・実引数から仮引数へは値のコピーが行われる(値渡し) ・この時、実引数には名前は不要で、指定順に仮引数に渡されていく  ※これを明示するために、実引数と仮引数に渡す変数名は同じにしないことが望ましい p.163 bmiclass.cs //p.163 bmiclass using System; class BMI { //インスタンス変数とメソッドを持ち利用されるクラス private double blm; //身長(m単位):インスタンス変数(クラス内部用) public double Calc(double bl, double bw) { //身長を体重を受取ってBMI値を返すメソッド blm = bl / 100.0; //m単位に換算し、インスタンス変数に格納 return bw / Math.Pow(blm, 2.0); //BMIを算出して返す } } class bmiclass { public static void Main() { string strBl, strBw; //入力用 double blcm, bwkg; Console.Write("身長(cm)---"); strBl = Console.ReadLine(); blcm = Double.Parse(strBl); Console.Write("体重(kg)---"); strBw = Console.ReadLine(); bwkg = Double.Parse(strBw); BMI bmi = new BMI(); //BMI計算用のクラスのインスタンスを生成 Console.WriteLine("BMIは{0:#.##}です", bmi.Calc(blcm, bwkg)); //身長と体重をメソッドに渡す } } アレンジ演習:p.163 bmiclass ・BMIクラスに計算式を返すSentenseメソッドを追加しよう ・Calcメソッドの実行により、インスタンス変数blmには身長(m単位)が格納されるので、これを用いて  「体重を【blmの値】の2乗で割った結果です」と表示しよう 作成例 //アレンジ演習:p.163 bmiclass using System; class BMI { //インスタンス変数とメソッドを持ち利用されるクラス private double blm; //身長(m単位):インスタンス変数(クラス内部用) public double Calc(double bl, double bw) { //身長を体重を受取ってBMI値を返すメソッド blm = bl / 100.0; //m単位に換算し、インスタンス変数に格納 return bw / Math.Pow(blm, 2.0); //BMIを算出して返す } public string Sentense() { //【追加】説明文を返す return "体重を" + blm + "の2乗で割った結果です"; //インスタンス変数の値を再利用 } } class bmiclass { public static void Main() { string strBl, strBw; //入力用 double blcm, bwkg; Console.Write("身長(cm)---"); strBl = Console.ReadLine(); blcm = Double.Parse(strBl); Console.Write("体重(kg)---"); strBw = Console.ReadLine(); bwkg = Double.Parse(strBw); BMI bmi = new BMI(); //BMI計算用のクラスのインスタンスを生成 Console.WriteLine("BMIは{0:#.##}です", bmi.Calc(blcm, bwkg)); //身長と体重をメソッドに渡す Console.WriteLine(bmi.Sentense()); //【追加】説明文を受け取って表示 } } アレンジ演習:p.163 bmiclass ・Shar(身長180cm、体重75kg)とAmuro(身長170cm、体重60kg)のBMIの差を表示する処理を追加しよう 作成例 //アレンジ演習:p.163 bmiclass using System; class BMI { //インスタンス変数とメソッドを持ち利用されるクラス private double blm; //身長(m単位):インスタンス変数(クラス内部用) public double Calc(double bl, double bw) { //身長を体重を受取ってBMI値を返すメソッド blm = bl / 100.0; //m単位に換算し、インスタンス変数に格納 return bw / Math.Pow(blm, 2.0); //BMIを算出して返す } public string Sentense() { //【追加】説明文を返す return "体重を" + blm + "の2乗で割った結果です"; //インスタンス変数の値を再利用 } } class bmiclass { public static void Main() { string strBl, strBw; //入力用 double blcm, bwkg; Console.Write("身長(cm)---"); strBl = Console.ReadLine(); blcm = Double.Parse(strBl); Console.Write("体重(kg)---"); strBw = Console.ReadLine(); bwkg = Double.Parse(strBw); BMI bmi = new BMI(); //BMI計算用のクラスのインスタンスを生成 Console.WriteLine("BMIは{0:#.##}です", bmi.Calc(blcm, bwkg)); //身長と体重をメソッドに渡す Console.WriteLine(bmi.Sentense()); //【追加】説明文を受け取って表示 BMI Shar = new BMI(); //SharのBMI計算用のインスタンスを生成 BMI Amuro = new BMI(); //AmuroのBMI計算用のインスタンスを生成 double s = Shar.Calc(180, 75); //SharのBMIを得る double a = Amuro.Calc(170, 60); //AmuroのBMIを得る Console.WriteLine("SharとAmuroのBMIの差は{0}", s - a); //差を表示 } } 参考:応用例:名前とbmi値をオブジェクトに持たせてみよう //アレンジ演習:p.163 bmiclass using System; class BMI { //インスタンス変数とメソッドを持ち利用されるクラス public string name; //名前 public double bmi; //BMI値 private double blm; //身長(m単位):インスタンス変数(クラス内部用) public double Calc(double bl, double bw) { //身長を体重を受取ってBMI値を返すメソッド blm = bl / 100.0; //m単位に換算し、インスタンス変数に格納 return bmi = bw / Math.Pow(blm, 2.0); //BMIを算出して返す } public string Sentense() { //【追加】説明文を返す return "体重を" + blm + "の2乗で割った結果です"; //インスタンス変数の値を再利用 } } class bmiclass { public static void Main() { string strBl, strBw; //入力用 double blcm, bwkg; Console.Write("身長(cm)---"); strBl = Console.ReadLine(); blcm = Double.Parse(strBl); Console.Write("体重(kg)---"); strBw = Console.ReadLine(); bwkg = Double.Parse(strBw); BMI bmi = new BMI(); //BMI計算用のクラスのインスタンスを生成 Console.WriteLine("BMIは{0:#.##}です", bmi.Calc(blcm, bwkg)); //身長と体重をメソッドに渡す Console.WriteLine(bmi.Sentense()); //説明文を受け取って表示 BMI Shar = new BMI(); //SharのBMI計算用のインスタンスを生成 Shar.name = "アズナブル";//【追加】 BMI Amuro = new BMI(); //AmuroのBMI計算用のインスタンスを生成 Amuro.name = "レイ";//【追加】 Shar.Calc(180, 75); //SharのBMIを得る //【変更】 Amuro.Calc(170, 60); //AmuroのBMIを得る //【変更】 Console.WriteLine("{0}と{1}のBMIの差は{2}", Shar.name, Amuro.name, Shar.bmi - Amuro.bmi); //【変更】差を表示 } } p.164(戻り値のないメソッド、引数のないメソッド) ・戻り値のないメソッドでは、戻り値型にvoidを指定する ・この場合、returnは必須ではなくなるが、指定は可能 ・returnを指定する事で、メソッドの途中で呼び出し側に戻ることができるので、効率が上がる  ※ メソッドの出口が複数化するので、推奨されない場合もある ・引数のないメソッドでは、仮引数の記述は不要だが、定義および呼び出しでは「()」が必要 p.165 noreturnvalue.cs //p.165 noreturnvalue.cs using System; class Kakeibo { //利用される家計簿クラス private int total = 0; //残高(直接操作されないようにprivateにする) public void nyukin(int en) { //入金(引数は入金額)メソッド:戻り値なし total += en; //入金額を残高に足しこむ Console.WriteLine("{0}円を入金しました", en); return; //なくても良い } public void shishutsu(int en) { //支出(引数は出金額)メソッド:戻り値なし if (total < en) { //残高を超えていたら Console.WriteLine("{0}円も支出できません", en); return; //なくても良い } else { //残高以下なら total -= en; //出金額を残高から差し引く Console.WriteLine("{0}円を支出しました", en); return; //なくても良い } } public void gettotal() { //残高の表示(引数なし)メソッド:戻り値なし if (total == 0) { //残高ゼロ? Console.WriteLine("残高はありません"); return; //なくても良い } else { Console.WriteLine("残高は{0}円です", total); return; //なくても良い } } } 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.165 noreturnvalue.cs ・各メソッドの最後のreturnは必要ないので削除しよう ・また、ifの最後のreturnがあれば、elseが不要になることを確認しよう 作成例 //アレンジ演習:p.165 noreturnvalue.cs using System; class Kakeibo { //利用される家計簿クラス private int total = 0; //残高(直接操作されないようにprivateにする) public void nyukin(int en) { //入金(引数は入金額)メソッド:戻り値なし total += en; //入金額を残高に足しこむ Console.WriteLine("{0}円を入金しました", en); //return; //なくても良い } public void shishutsu(int en) { //支出(引数は出金額)メソッド:戻り値なし if (total < en) { //残高を超えていたら Console.WriteLine("{0}円も支出できません", en); return; //メソッドの途中で戻る } total -= en; //出金額を残高から差し引く Console.WriteLine("{0}円を支出しました", en); //return; //なくても良い } public void gettotal() { //残高の表示(引数なし)メソッド:戻り値なし if (total == 0) { //残高ゼロ? Console.WriteLine("残高はありません"); return; //メソッドの途中で戻る } Console.WriteLine("残高は{0}円です", total); //return; //なくても良い } } 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.166(カプセル化) ・このプログラムの「private int total = 0; //残高(直接操作されないようにprivateにする)」のように、データメンバを守ることをカプセル化という ・特に、データの特性により最大値、最小値が決まっている場合(負の数禁止も含む)や、直接操作されることによる危険性がある場合はカプセル化が必要 ・基本的には、データメンバは全てprivateにし、これを操作するメソッドをpublicにする ・このプログラムでは、totalの値が負の数にならないようにカプセル化している p.167 コンストラクタ ・newによりインスタンスを生成すると、自動的に実行される特別なメソッドがあり、これをコンストラクタという。 ・コンストラクタの有無は自由で、記述しないと自動的に中身のないコンストラクタが作られて動作する ・コンストラクタを記述する事で、インスタンスを生成するときに行いたい事を指定できる ・これは、主にデータメンバへの初期値の設定や、複雑なメソッドを持つクラスにおける開始処理などに用いる  例: Monster rimuru = new Monster(100, 500); //コンストラクタにHPとMPを渡して初期値にしてもらう ・コンストラクタは特別なメソッドで名前がなくクラス名になり、戻り値はなく、必ずpublicとする。 p.167 construct01.cs //p.167 construct01.cs using System; class MyClass { //部品クラス int x; //インスタンス変数 public void showx() { //xの値を表示するメソッド Console.WriteLine("x = " + x); } // コンストラクタ クラスと同じ名前、戻り値なし public MyClass() { x = 10; //インスタンス変数の初期値を設定 Console.WriteLine("xに10を代入しました"); //テスト用 } } class construct01 { //実行用クラス public static void Main() { //実行用メソッド // newしたときにコンストラクタが呼ばれます MyClass mc = new MyClass(); mc.showx(); } } アレンジ演習:p.167 construct01.cs ・複数のオブジェクトを生成すると、その都度、コンストラクタが動作することを確認しよう 作成例 //アレンジ演習:p.167 construct01.cs using System; class MyClass { //部品クラス int x; //インスタンス変数 public void showx() { //xの値を表示するメソッド Console.WriteLine("x = " + x); } // コンストラクタ クラスと同じ名前、戻り値なし public MyClass() { x = 10; //インスタンス変数の初期値を設定 Console.WriteLine("xに10を代入しました"); //テスト用 } } class construct01 { //実行用クラス public static void Main() { //実行用メソッド // newしたときにコンストラクタが呼ばれる MyClass mc = new MyClass(); mc.showx(); MyClass md = new MyClass(); //【追加】再度コンストラクタが呼ばれる } } p.168(コンストラクタの引数とオーバーロード) ・コンストラクタもメソッドの一種なので、パラメータリストを指定できる  例: public Monster(int h, int m) { hp = h; mp = m; } ・これはnewによって呼び出す時に、その値を指定する  例: Monster rimuru = new Monster(100, 500); //コンストラクタにHPとMPを渡して初期値にしてもらう ・パラメータリストを指定したコンストラクタと指定しないコンストラクタを混在できる ・また、呼び出しにおいて区別できるのであれば、パラメータリストを指定したコンストラクタを複数記述できる ・このことをオーバーロードという 例: public Monster() { hp = 10; mp = 20; } //コンストラクタ@  public Monster(int h) { hp = h; mp = 20; } //コンストラクタA  public Monster(int h, int m) { hp = h; mp = m; } //コンストラクタB  : Monster veldra = new Monster(); //コンストラクタ@を呼ぶ Monster slalin = new Monster(100); //コンストラクタAを呼ぶ Monster rimuru = new Monster(100, 500); //コンストラクタBを呼ぶ 提出:アレンジ演習:p.167 construct01.cs 次回予告:p.169「construct02.cs」から