Day 33 のゴールと全体像
Day 33 のテーマは コンストラクタ です。 いよいよ「オブジェクトが生まれる瞬間」を、ちゃんとコントロールできるようになっていきます。
学ぶことは次の 4 つです。
- コンストラクタ
- 初期化
- 引数付きコンストラクタ
- オーバーロード
ざっくり言うと、
「
newしたときに、オブジェクトをどう準備させるか」
を学ぶ回だと思って読んでいただけると、イメージしやすいと思います。
コンストラクタとは何か
「生まれた瞬間に呼ばれる特別なメソッド」
コンストラクタは、
オブジェクトが
newされた瞬間に、自動で呼ばれる特別なメソッド
です。
特徴を整理すると、
- クラス名と同じ名前を持つ
- 戻り値の型を書かない(
voidも書かない) new クラス名(...)としたときに自動で実行される
まずは、シンプルなコンストラクタの例を見てみましょう。
class Person
{
public string Name;
public int Age;
// コンストラクタ(引数なし)
public Person()
{
Console.WriteLine("Person のインスタンスが生成されました。");
Name = "名無し"; // デフォルトの名前
Age = 0; // デフォルトの年齢
}
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {Age} 歳です。");
}
}
class Program
{
static void Main(string[] args)
{
// ここでコンストラクタが自動的に呼ばれます
Person p = new Person();
p.Introduce();
Console.ReadLine();
}
}
C#このコードを実行すると、
new Person()のタイミングでPerson()コンストラクタが呼ばれる- コンストラクタの中で
NameとAgeが初期化される - そのあとで
Introduce()が呼ばれる
という流れになります。
重要ポイント:
- コンストラクタは「オブジェクトの初期設定」をする場所です。
newした瞬間に必ず呼ばれるので、「必ずやっておきたい処理」を書くのに向いています。
初期化をコンストラクタにまとめる意味
「作ったあとに設定する」より「作るときに設定する」
コンストラクタがない場合、オブジェクトの初期化はこんな感じになります。
Person p = new Person();
p.Name = "太郎";
p.Age = 20;
C#もちろんこれでも動きますが、
- 名前を設定し忘れる
- 年齢を設定し忘れる
といった「初期化漏れ」が起きやすくなります。
そこで、
「作るときに、必要な情報を必ず渡させる」
というスタイルにすると、ミスが減ります。 これが 引数付きコンストラクタ です。
引数付きコンストラクタ
「作るときに必要な情報を渡す」スタイル
引数付きコンストラクタは、
「
newするときに、初期化に必要な値を渡せるコンストラクタ」
です。
先ほどの Person を、引数付きコンストラクタで書き直してみます。
class Person
{
public string Name;
public int Age;
// 引数付きコンストラクタ
public Person(string name, int age)
{
Console.WriteLine("Person のインスタンスが生成されました。(引数付き)");
Name = name;
Age = age;
}
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {Age} 歳です。");
}
}
class Program
{
static void Main(string[] args)
{
// ここで name と age を渡しながらインスタンスを生成します
Person p = new Person("太郎", 20);
p.Introduce();
Console.ReadLine();
}
}
C#この形だと、
Personを作るときに、必ずnameとageを渡さないといけない- 「名前が未設定のまま」「年齢が未設定のまま」という状態を防げる
というメリットがあります。
重要ポイント:
- 引数付きコンストラクタは「必須情報を強制する」ための仕組みとして、とてもよく使われます。
- クラスを設計するとき、「このクラスは何がないと成立しないか?」を考えると、引数付きコンストラクタの形が見えてきます。
コンストラクタのオーバーロード
「状況に応じて、いくつかの作り方を用意する」
コンストラクタは、メソッドと同じように オーバーロード できます。 オーバーロードとは、
「同じ名前で、引数のパターンが違うメソッドを複数用意すること」
でしたね。
コンストラクタの場合も同じで、
- 引数なしのコンストラクタ
- 引数付きのコンストラクタ
などを、同じクラスの中に共存させることができます。
Person クラスのコンストラクタオーバーロード例
class Person
{
public string Name;
public int Age;
// 1. 引数なしコンストラクタ
public Person()
{
Console.WriteLine("引数なしコンストラクタが呼ばれました。");
Name = "名無し";
Age = 0;
}
// 2. 引数付きコンストラクタ
public Person(string name, int age)
{
Console.WriteLine("引数付きコンストラクタが呼ばれました。");
Name = name;
Age = age;
}
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {Age} 歳です。");
}
}
class Program
{
static void Main(string[] args)
{
// 引数なしコンストラクタを使う
Person p1 = new Person();
p1.Introduce();
// 引数付きコンストラクタを使う
Person p2 = new Person("花子", 25);
p2.Introduce();
Console.ReadLine();
}
}
C#このように、
- 「とりあえずデフォルト値で作る」
- 「ちゃんと値を指定して作る」
という 2 パターンを用意しておくことができます。
重要ポイント:
- コンストラクタのオーバーロードは、「使う側の自由度」を上げるためのテクニックです。
- ただし、パターンが増えすぎると分かりにくくなるので、「本当に必要な作り方だけ」に絞るのがコツです。
コンストラクタ+プロパティの組み合わせ
Day 32 の内容とつなげてみる
Day 32 で学んだ「プロパティ」と、今回の「コンストラクタ」はとても相性が良いです。
例えば、Product クラスをコンストラクタ+プロパティで設計すると、こんな感じになります。
using System;
class Product
{
// 価格はフィールド+プロパティで管理
private int price;
public int Price
{
get { return price; }
set
{
if (value < 0)
{
price = 0;
}
else
{
price = value;
}
}
}
// 名前は自動実装プロパティ
public string Name { get; set; }
// 引数付きコンストラクタ
public Product(string name, int price)
{
Name = name;
Price = price; // set 経由でチェックされます
}
// 引数なしコンストラクタ(オーバーロード)
public Product()
{
Name = "不明";
Price = 0;
}
public void PrintInfo()
{
Console.WriteLine($"商品名: {Name}, 価格(税抜): {Price}");
}
}
class Program
{
static void Main(string[] args)
{
// 引数付きコンストラクタで作成
Product p1 = new Product("ノート", 100);
p1.PrintInfo();
// 引数なしコンストラクタで作成
Product p2 = new Product();
p2.PrintInfo();
Console.ReadLine();
}
}
C#ここでは、
- コンストラクタで「初期値」を決める
- プロパティで「値のチェック」を行う
という役割分担になっています。
重要ポイント:
- コンストラクタは「最初の状態を決める場所」
- プロパティは「その後の変更を管理する場所」
と考えると、設計がすっきりします。
Day 33 用の練習テンプレート
最後に、コンストラクタの練習に使えるテンプレートを紹介します。 自分の好きなテーマに置き換えて遊んでみてください。
ユーザークラスのテンプレート
using System;
class User
{
// 自動実装プロパティ
public string UserName { get; set; }
public string Email { get; set; }
// 引数なしコンストラクタ
public User()
{
UserName = "guest";
Email = "guest@example.com";
Console.WriteLine("ゲストユーザーが生成されました。");
}
// 引数付きコンストラクタ
public User(string userName, string email)
{
UserName = userName;
Email = email;
Console.WriteLine("ユーザーが生成されました。");
}
public void PrintInfo()
{
Console.WriteLine($"UserName: {UserName}, Email: {Email}");
}
}
class Program
{
static void Main(string[] args)
{
// ゲストユーザー
User guest = new User();
guest.PrintInfo();
// 通常ユーザー
User normal = new User("mono_user", "mono@example.com");
normal.PrintInfo();
Console.ReadLine();
}
}
C#このテンプレートをベースにして、
Studentクラスで「名前+点数」をコンストラクタで受け取るBookクラスで「タイトル+著者+ページ数」を初期化するCarクラスで「メーカー+モデル+年式」を設定する
など、いろいろな「コンストラクタ付きクラス」を作ってみると、 コンストラクタの使い方が自然と身についていきます。
Day 33 のまとめ
Day 33 では、
- コンストラクタ = オブジェクト生成時に自動で呼ばれる特別なメソッド
- 初期化 = コンストラクタで「最初の状態」を決めること
- 引数付きコンストラクタ = 必須情報を渡させるための仕組み
- オーバーロード = 複数の作り方を用意して、使う側の自由度を上げる
という流れで、 「オブジェクトが生まれる瞬間を設計する」という感覚を育てました。
この先、
- クラス同士が関係し合う設計
- より複雑なオブジェクトのライフサイクル管理
に進んでいくとき、 今日学んだコンストラクタは、必ずと言っていいほど登場します。
ぜひ、
- 自分でクラスを 1 つ考えて、引数なし/引数付きコンストラクタを両方作ってみる
- 「このクラスは何がないと成立しないか?」を考えて、必須情報をコンストラクタの引数にしてみる
- プロパティと組み合わせて、「初期化」と「その後の変更」をきれいに分けてみる
といった練習を通して、 コンストラクタを「ただの文法」ではなく、 「オブジェクトの生まれ方をデザインする道具」として、しっかり自分のものにしていってください。
