講義メモ 後半

p.201 引数が可変個のメソッド

・メソッドの引数にparamsキーワードと配列を指定することで、引数が可変個のメソッドになる
・よって、同型の引数をいくつでも指定できる1メソッドが記述できる
・書式: アクセス修飾子 戻り値型 メソッド名(params 配列型[] 仮引数) {…}
・例: public void dispall(params int[] p) {…}
・メソッド内部では仮引数を配列として、各引数はその要素になる
・よって、引数の数は、仮引数.Lengthで得ると良い
・引数が0個でもかまわないが、要素数0の配列になるので、要素を使用すると異常終了する
例:
public void dispall(params int[] p) {
    foreach(var w in p) { //仮引数の配列の全要素について繰返す
        Console.WriteLine(w);
    }
}

アレンジ演習:p.201 params01.cs

・forは前判定繰返しなので、animal.lengthが0の場合、繰返し内容は1度も実行されない。よって、if文は不要なことを確認しよう
・for文をforeach文にしよう
・引数に数値を含むとエラーになることを確認しよう

作成例

//アレンジ演習:p.201 params01.cs
using System;
class MyClass {
    public void show(params string[] animal) { //可変個引数
        //if (animal.Length == 0) //【削除】
        //    return; //【削除】
        foreach (var w in animal) {
            Console.WriteLine("{0}さんがいます", w);
        }
    }
    public void show(string animal) { //
        foreach (var w in animal) {
            Console.WriteLine("{0}さがいます", w);
        }
    }
}
class params01 {
    public static void Main() {
        int[] x = {0,1,2};
        MyClass mc = new MyClass();
        mc.show();
        mc.show("きりん", "ぞう", "かば");
        //mc.show("きりん", "ぞう", "かば", 1); //文字列に暗黙変換ができない引数があるとエラー
    }
}

補足:可変個引数と通常の引数の共存

・可変個引数と通常の引数は共存できる。ただし、可変個引数を末尾にすること
・よって、可変個引数は1つしか指定できない
 例:public void show(int i, params string[] animal) {…}
 こうすると、mc.show(0)、mc.show(0, "hoo")、mc.show(0, "hoo", "voo"); などの呼び出しが可能。
 ただし、mc.show()、mc.show("hoo")などの呼び出しはエラーになる。

補足:可変個引数とオーバーロード

・呼び出しにおいて区別できる限り、可変個引数を用いたメソッドのオーバーロードは可能
・ただし、引数の与え方により、呼び出しが区別できない場合は、呼び出し側がエラーになる
 例:void all(params int[] a) {…}、void all(params string[] a) {…} の場合:
 こうすると、all(0)、all(0, 1)、all("hoo", "voo"); などの呼び出しが可能。
 ただし、all()、mc.show(0, "hoo")などの呼び出しはエラーになる。
・また、可変個引数を用いたメソッドと可変個引数を用いないメソッドのオーバーロードも可能
・ただし、引数の与え方により、呼び出しが区別できない場合は、用いないメソッドが優先される

ミニ演習:mini0810a.cs

・可変個引数を用いたメソッドと可変個引数を用いないメソッドのオーバーロードで、引数の与え方により、呼び出しが区別できない場合は、
 用いないメソッドが優先されることを試そう

作成例

//ミニ演習:mini0810a.cs
using System;
class MyClass {
    public void show(params string[] animal) { //可変個引数なメソッド①
        foreach (var w in animal) {
            Console.WriteLine("{0}さんがいます", w);
        }
    }
    public void show(string animal) { //可変個引数ではないメソッド②
        Console.WriteLine("{0}がいます", animal);
    }
}
class params01 {
    public static void Main() {
        int[] x = {0,1,2};
        MyClass mc = new MyClass();
        mc.show("ひと"); //①②の両方が当てはまるが②が実行される
        mc.show("きりん", "ぞう", "かば"); //①が実行される
    }
}

p.202 静的メンバ

・通常、クラスの各メンバはインスタンスに所属する
 例:Slimeクラスにhpを定義すると、Slimeクラスのインスタンスslalinに所属し、slalin.hpになる
・しかし、インスタンスに所属する必要がないような=クラスに所属するメンバも記述できる
・それが静的メンバで、staticを前置して示す
 例:Slimeクラスに「生成したスライム数」を持たせる場合、インスタンスには所属しないので、クラスで持つ方が良い
・また、インスタンス変数を全く用いないメソッドもクラスで持つ方が良く、これを静的メソッドという
・静的メンバはクラスに所属するので「クラス名.」を前に付けて実行する
・よって、静的メンバはインスタンスの生成をしなくても利用できる
・なお、Console.WriteLineは、Consoleクラスの静的メソッドなので「Console.」を前につけている
・また、Mathクラスのメンバの大半は静的メンバ(例:Math.PI)
・近い理由で、Mainメソッドも静的メソッドである必要があるので「static」を前置する
・逆に言えば、静的メンバはインスタンスごとにはならない特殊なものであり、オブジェクト指向のメリットを生かせないので乱用は避けること。
※ つまり、設計図に直接データを書き込んでいるようなイメージ

アレンジ演習:p.203 static01.cs

・デフォルトコンストラクタを追加し、その中で静的メンバ変数xをインクリメントしよう
・Mainメソッドで静的メンバ変数xの最初の値を10ではなく0にしよう
・そして、MyClassのインスタンスを生成してから、ShowX()メソッドを実行することを繰返してみよう

作成例

// static01.cs
using System;
class MyClass {
    public static int x; //静的データメンバ
    public static void showX() { //静的メソッド
        Console.WriteLine("x = {0}", x); //静的データメンバのみを使う
    }
    public MyClass() { //【以下追加】デフォルトコンストラクタ
        x++; //静的データメンバをインクリメント
    }
}
class static01 {
    public static void Main() { //実はMainも静的メソッド
        MyClass.x = 0; //【変更】静的データメンバなので「クラス名.」で利用可能
        MyClass.showX(); //静的メソッド「クラス名.」で実行可能
        new MyClass(); //【以下追加】デフォルトコンストラクタを呼ぶ
        MyClass.showX(); //1になっている
        new MyClass(); //デフォルトコンストラクタを呼ぶ
        MyClass.showX(); //2になっている
    }
}

p.204 静的クラス

・静的メンバのみによるクラスは、静的クラスにすることができる
・書式: static class クラス名 {…}
・義務はないが、静的クラスにしておくことで、誤って静的ではないメンバが出現することを防止できる
 ※ 例えば、固定データのみを持つクラスや、数値関数のみを持つクラスなど(特殊な事例)

アレンジ演習:p.204 static02.cs

・静的クラスにインスタンスメンバを追記してエラーになることを確認しよう

作成例

//アレンジ演習:p.204 static02.cs
using System;
static class MyClass { //静的クラス
    public static int x; //静的データメンバ
    // int y; //インスタンス変数を記述するとエラー
    public static void showX() { //静的メソッド
        System.Console.WriteLine("x = {0}", x);
    }
    // void foo() { } //インスタンスメソッドを記述するとエラー
}
class static02 {
    public static void Main() {
        MyClass.x = 10; //静的データメンバを用いる
        MyClass.showX(); //静的メソッドを実行
    }
}

p.205 静的メンバとインスタンスメンバの混在

・1クラスに静的メンバとインスタンスメンバの混在が可能だが、下記のルールがある
① 静的メソッドはインスタンス変数を扱えない(区別できないので)
② 静的メソッドはインスタンスメソッドを呼べない(〃)
③ 静的メソッドはthisを使えない(thisはインスタンスを指すので)
・なお、インスタンスメンバから静的メンバへのアクセスには制限はない(クラスに1つしかないので)

p.205 static03.cs 解説図

 

アレンジ演習:p.205 static03.cs

・静的メソッドSetCatTail()の中の「// name = "マイケル";」をコメントアウトしないと、どういうエラーになるか確認しよう
・静的メソッドSetCatTail()の中で、インスタンスメソッドShowCat()を呼ぶとエラーになることを確認しよう
・静的メソッドSetCatTail()の中で、thisを用いるとエラーになることを確認しよう
・以上は、確認後、コメントアウトすること

提出:アレンジ演習:p.205 static03.cs

コメントを残す

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