・「p.168 コンストラクタ:コンストラクタのオーバーロード」から
p.167 コンストラクタ:コンストラクタの引数(再掲載)
・メソッドと同様にコンストラクタにも引数が指定できる
・引数を指定したコンストラクタを呼び出すには、newにおいてカッコ内に引数型と引数を記述する
・定義書式②: public クラス名(引数型 引数名, …) {処理内容}
例: public Slime(int h, int p) { hp = h; mp = p; }
・呼び出し法: new クラス名(値や式, …);
p.168 コンストラクタ:コンストラクタのオーバーロード
・コンストラクタを含むメソッドは、引数で呼び出し方を区別できるのであれば、同じ名前で定義しても良い
※ C++の関数も同様だが、C言語などの関数では不可
・「呼び出し方を区別できる」とは、引数の数や引数型や順番の違いのこと
・この「引数の数や引数型や順番の違う」コンストラクタのことをコンストラクタのオーバーロードという
・例: public Monster(){…} //①引数のないコンストラクタ
・例: public Monster(int hp){…} //②HPのみを引数で渡すコンストラクタ
・例: public Monster(int hp, int mp){…} //③HPとMPを引数で渡すコンストラクタ
・例: public Monster(string name){…} //④nameのみを引数で渡すコンストラクタ
・上記は呼び出し方によって自動的に使い分けられる
・例: Monster Slalin = new Monster(); //①が呼ばれる
・例: Monster Hoimin = new Monster(20); //②が呼ばれ、20はHPに用いられる
・例: Monster Rimuru = new Monster(100, 200); //③が呼ばれ、100はHPに、200はMPに用いられる
・例: Monster Veldra = new Monster("ヴェルドラ"); //④が呼ばれ、"ヴェルドラ"は名前に用いられる
・メソッドのオーバーロードの場合、名前と引数の数や引数型や順番の違いで判別する
・この「名前が同じで、引数の数や引数型や順番の違う」メソッドのことをメソッドのオーバーロードという
・例: public void add(){…} //①引数のないメソッド
・例: public void add(int hp){…} //②HPのみを引数で渡すメソッド
・例: public void add(int hp, int mp){…} //③HPとMPを引数で渡すメソッド
・上記は呼び出し方によって自動的に使い分けられる
・例: add(); //①が呼ばれる
・例: add(20); //②が呼ばれ、20はHPに用いられる
・例: add(100, 200); //③が呼ばれ、100はHPに、200はMPに用いられる
・なお、メソッド名と、引数の数や引数型や順番の情報を合わせて、メソッドのシグニチャという
・コンストラクタは戻り値がないが、メソッドの戻り値型はオーバーロードのシグニチャに含まれない
・戻り値型のみが異なる場合、呼び出し方によって自動的に使い分けることはできないので、エラーになる
・例: public int add(int hp, int mp){…} //④エラー(③と同じシグニチャなので)
アレンジ演習:p.169 construct02.cs
・名前と年齢を渡すコンストラクタのオーバーロードを追加しよう ・これを呼び出す処理を追記しよう
作成例
//p.169 construct02.cs
using System;
class MyClass {
private string name; //フィールド
private int age;
private string address;
public void Show() { //メソッド
string toshi;
if (age == -1) {
toshi = "不明";
} else {
toshi = age.ToString(); //整数を文字列に変換するメソッド(Int32クラス)
}
Console.WriteLine("氏名:{0} 住所:{1} 年齢:{2}", name, address, toshi);
}
public MyClass(string str) { //コンストラクタ①(文字列)
name = str;
address = "不定";
age = -1;
}
public MyClass(int x) { //コンストラクタ②(整数)
age = x;
name = "不明";
address = "不定";
}
public MyClass(string str1, string str2, int x) { //コンストラクタ③(文字列,文字列,整数列)
name = str1;
address = str2;
age = x;
}
public MyClass(string str1, int x) { //【以下追加】コンストラクタ④(文字列,整数列)
name = str1;
address = "不定";
age = x;
}
}
class construct01 { //実行用クラス
public static void Main() {
MyClass mc1 = new MyClass(18); //コンストラクタ②(整数)が呼ばれる
MyClass mc2 = new MyClass("粂井康孝"); //コンストラクタ①(文字列)が呼ばれる
MyClass mc3 = new MyClass("田中太郎", "東京都", 32); //コンストラクタ③(文字列,文字列,整数列)が呼ばれる
mc1.Show();
mc2.Show();
mc3.Show();
MyClass mc4 = new MyClass("ヴェルファイア", 200); //【以下追加】コンストラクタ④(文字列,整数列)が呼ばれる
mc4.Show();
}
}
p.168 コンストラクタ:コンストラクタのオーバーロードとデフォルトコンストラクタ
・通常、デフォルトコンストラクタは自動的に用意される ・自前で記述することもできる ・なお、コンストラクタのオーバーロードがされている場合、デフォルトコンストラクタは自動的に用意されない ・よって、自前で記述する必要がある
アレンジ演習:p.169 construct02.cs・つづき
・Mainメソッドに、引数のないインスタンス生成を追記し、どうなるか確認しよう ・必要であれば、デフォルトコンストラクタを自前で記述し、動作を確認しよう
作成例
//アレンジ演習:p.169 construct02.cs
using System;
class MyClass {
private string name; //フィールド
private int age;
private string address;
public void Show() { //メソッド
string toshi;
if (age == -1) {
toshi = "不明";
} else {
toshi = age.ToString(); //整数を文字列に変換するメソッド(Int32クラス)
}
Console.WriteLine("氏名:{0} 住所:{1} 年齢:{2}", name, address, toshi);
}
public MyClass(string str) { //コンストラクタ①(文字列)
name = str;
address = "不定";
age = -1;
}
public MyClass(int x) { //コンストラクタ②(整数)
age = x;
name = "不明";
address = "不定";
}
public MyClass(string str1, string str2, int x) { //コンストラクタ③(文字列,文字列,整数列)
name = str1;
address = str2;
age = x;
}
public MyClass(string str1, int x) { //コンストラクタ④(文字列,整数列)
name = str1;
address = "不定";
age = x;
}
public MyClass() { //デフォルトコンストラクタ⑤()
name = "不明";
address = "不定";
age = -1;
}
}
class construct01 { //実行用クラス
public static void Main() {
MyClass mc1 = new MyClass(18); //コンストラクタ②(整数)が呼ばれる
MyClass mc2 = new MyClass("粂井康孝"); //コンストラクタ①(文字列)が呼ばれる
MyClass mc3 = new MyClass("田中太郎", "東京都", 32); //コンストラクタ③(文字列,文字列,整数列)が呼ばれる
mc1.Show();
mc2.Show();
mc3.Show();
MyClass mc4 = new MyClass("ヴェルファイア", 200); //コンストラクタ④(文字列,整数列)が呼ばれる
mc4.Show();
MyClass mc5 = new MyClass(); //【以下追加】デフォルトコンストラクタ⑤が呼ばれる
mc5.Show();
}
}
p.171 デストラクタ(デストラクタ)
・プログラムの中で生成されたオブジェクト(インスタンス)は、基本的に、プログラムの終了時に破棄される ・C#では、プログラマが意図的にオブジェクト(インスタンス)を削除(無効化)しても、即時には処理されない ・C#などではガベージコレクション機能があり、システム側で適時にオブジェクトの掃除を行うことで、メモリの利用効率を高めている ・なお、プログラム内でガベージコレクション機能を実行させることはできない ・参照されなくなったオブジェクトはガベージコレクションの対象になるので、参照を空にしたり、他のオブジェクトを指すようにすることで、 オブジェクトを実質的に消すことは可能。 ・例: Monster m = new Monster(); Monster n = new Monster(); m = n; //最初のnewで生成したオブジェクトmは消される
p.171 デストラクタ(ガベージコレクション)
・オブジェクトの生成時に呼ばれるコンストラクタに対して、オブジェクトの消去時に呼ばれる特殊なメソッドがデストラクタ
・デストラクタを直接呼び出したり、動作タイミングを成業することはできない(ガベージコレクションと同様)
・デストラクタは内容が空のものが自動的に用意されるが自前で記述することもできる
・コンストラクタが準備作業を行うことに対して、デストラクタは後始末に用いることができる
・定義書式: ~クラス名(){…}
・コンストラクタとは異なり、引数は指定できない(よってオーバーロードも不可)
・戻り値はなく、voidを指定することもできない
・複数のオブジェクトが消された場合、デストラクタの実行順序は不定だが確実に実行される
アレンジ演習:p.172 destruct01.cs
・変数dt2、dt3を使用せず、変数dt1のみで3つのオブジェクトを順に扱うようにしたらどうなるか確認しよう ⇒現状と同様(メモリが非常に少なければ、ガベージコレクションが起こり、デストラクタが動作する可能性はある)
作成例
//アレンジ演習:p.172 destruct01.cs
using System;
class DestructTest {
int x;
// デストラクタ
~DestructTest() { //戻り値型無し、引数無し
Console.WriteLine("デストラクタが呼ばれました");
Console.WriteLine("xは{0}です", x);
}
// 引数付きコンストラクタ
public DestructTest(int n) { //戻り値型無し、引数有
Console.WriteLine("コンストラクタが呼ばれました");
x = n;
Console.WriteLine("xに{0}を代入しました", n);
}
}
class destruct {
public static void Main() {
DestructTest dt1 = new DestructTest(1); //コンストラクタが呼ばれる①
Console.WriteLine("dt1生成");
dt1 = new DestructTest(2); //コンストラクタが呼ばれる②(これで①は不要になる)
Console.WriteLine("dt1上書①");
dt1 = new DestructTest(3); //コンストラクタが呼ばれる③(これで②も不要になる)
Console.WriteLine("dt1上書②");
Console.ReadLine(); //入力待ち
} //この直後にデストラクタが3つ呼ばれる
}