Day 32 のゴールと全体像
Day 32 では、オブジェクト指向の中でもとても大事な「クラスの中身の扱い方」を学びます。 テーマは次の 5 つです。
- フィールド
- プロパティ
getset- 自動実装プロパティ
ざっくり言うと、
「クラスの中のデータを、どう安全に・きれいに扱うか」
を学ぶ回だと思って読んでいただけるとよいです。 雑誌の記事を読むような気持ちで、肩の力を抜いて進んでいきましょう。
フィールドとは何か
クラスの「素のデータ置き場」
まずはフィールドからです。 フィールドは、
「クラスの中に直接書かれた、データを入れておく変数」
のことです。
たとえば、前回の Person クラスをもう一度見てみます。
// 人を表すクラス
class Person
{
// フィールド(クラスの中の変数)
public string Name; // 名前
public int Age; // 年齢
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {Age} 歳です。");
}
}
C#ここで Name と Age が「フィールド」です。
- クラスの中に
- 型+名前で
- そのまま宣言されている変数
これがフィールドだ、と覚えておくとよいです。
フィールドの問題点
フィールドはシンプルで分かりやすいのですが、 そのまま外から public で丸見えにしてしまうと、少し困ることがあります。
例えば、年齢に「マイナスの値」が入ってしまうかもしれません。
Person p = new Person();
p.Name = "太郎";
p.Age = -100; // 本来ありえない値ですが、代入できてしまいます
C#こういう「おかしな値」を防ぎたいときに登場するのが、 次に説明する プロパティ です。
プロパティとは何か
「フィールドへの出入り口」を作るイメージ
プロパティは、
「フィールドにアクセスするための、少し賢い窓口」
だと思ってください。
- 外からは「普通の変数みたい」に見える
- 中では「値をチェックしたり、加工したり」できる
そんな仕組みです。
まずは、フィールド+プロパティの基本形を見てみましょう。
class Person
{
// 実際のデータを持つフィールド(外からは直接触らせない)
private string name;
private int age;
// フィールドにアクセスするためのプロパティ
public string Name
{
get
{
// 値を取り出すときの処理
return name;
}
set
{
// 値を代入するときの処理
name = value;
}
}
public int Age
{
get
{
return age;
}
set
{
// 年齢におかしな値が入らないようにチェック
if (value < 0)
{
age = 0; // マイナスが来たら 0 にしておく、などのルールを決められます
}
else
{
age = value;
}
}
}
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {Age} 歳です。");
}
}
C#ここでのポイントは、
- 実際のデータは
privateなフィールドname/ageに持たせる - 外からは
Name/Ageというプロパティを通してアクセスさせる setの中で「値のチェック」ができる
という構造になっていることです。
get と set をもう少し丁寧に
get:値を「取り出す」側
get は、
「プロパティの値を読み取るときに呼ばれる処理」
です。
public int Age
{
get
{
return age; // フィールドの値を返す
}
set
{
// 代入時の処理
}
}
C#外からは、こんなふうに使います。
Person p = new Person();
p.Age = 20; // set が呼ばれる
Console.WriteLine(p.Age); // get が呼ばれる
C#set:値を「入れる」側
set は、
「プロパティに値を代入するときに呼ばれる処理」
です。
set の中では、特別な変数 value が使えます。
valueには「代入されようとしている値」が入っています
public int Age
{
get
{
return age;
}
set
{
if (value < 0)
{
age = 0;
}
else
{
age = value;
}
}
}
C#このように、set の中で「値のチェック」や「補正」を行うことで、 クラスの中のデータを安全に保つことができます。
重要ポイント:
getは「読み取り」、setは「書き込み」の窓口です。setの中でvalueをチェックすることで、不正な値を防げます。
自動実装プロパティ
シンプルに書きたいときのショートカット
毎回、
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
C#と書くのは、正直ちょっと面倒です。 「特にチェックも加工もしない、ただの出入り口」でいい場合は、 もっと簡単に書きたいですよね。
そこで登場するのが 自動実装プロパティ です。
class Person
{
// 自動実装プロパティ
public string Name { get; set; }
public int Age { get; set; }
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {Age} 歳です。");
}
}
C#これだけで、
- 裏側に「匿名のフィールド」が自動的に用意される
get/setも「そのまま代入・そのまま返す」形で自動生成される
という、とても便利な仕組みになっています。
使い方はフィールドとほぼ同じ感覚です。
Person p = new Person();
p.Name = "太郎"; // set が呼ばれる
p.Age = 20; // set が呼ばれる
Console.WriteLine(p.Name); // get が呼ばれる
Console.WriteLine(p.Age); // get が呼ばれる
C#重要ポイント:
- 「特にチェックしないプロパティ」は、自動実装プロパティで書くのが定番です。
- 後から「やっぱりチェックしたい」と思ったら、通常の
get/set付きプロパティに書き換えればOKです。
フィールド+プロパティの設計パターン
「守りたいデータ」はフィールド+プロパティ
実務でもよく使われるパターンは、
- フィールドは
privateにして外から直接触らせない - プロパティは
publicにして、そこからアクセスさせる - プロパティの
setで値をチェックする
という形です。
例として、「年齢は 0〜120 の範囲にしたい」というクラスを考えてみます。
class Person
{
private int age; // 実データは private フィールドに
public int Age
{
get
{
return age;
}
set
{
// 0〜120 の範囲に制限する
if (value < 0)
{
age = 0;
}
else if (value > 120)
{
age = 120;
}
else
{
age = value;
}
}
}
public string Name { get; set; } // 名前は特に制限しないので自動実装プロパティ
}
C#このクラスを使うと、
Person p = new Person();
p.Age = -10; // 0 に補正される
p.Age = 200; // 120 に補正される
p.Age = 30; // 30 のまま
p.Name = "花子";
Console.WriteLine($"名前: {p.Name}, 年齢: {p.Age}");
C#こうして、
「クラスの外からは自由に見えるけれど、 中ではちゃんとルールを守らせる」
という状態を作ることができます。
Day 32 用の練習テンプレート
最後に、Day 32 の内容を練習するための、 少しだけ実用的なクラスのテンプレートを紹介します。
商品クラスの例
using System;
class Product
{
// 価格はフィールド+プロパティでしっかり管理
private int price;
public int Price
{
get
{
return price;
}
set
{
if (value < 0)
{
price = 0; // マイナス価格はありえないので 0 に補正
}
else
{
price = value;
}
}
}
// 名前は自動実装プロパティでシンプルに
public string Name { get; set; }
// 税込み価格を計算するメソッド
public int GetPriceWithTax()
{
return (int)(Price * 1.10); // 消費税 10% と仮定
}
// 情報を表示するメソッド
public void PrintInfo()
{
Console.WriteLine($"商品名: {Name}, 価格(税抜): {Price}, 価格(税込): {GetPriceWithTax()}");
}
}
class Program
{
static void Main(string[] args)
{
Product p = new Product();
p.Name = "ノート";
p.Price = 100;
p.PrintInfo();
// おかしな値を入れてみる
p.Price = -500; // set の中で 0 に補正されます
p.PrintInfo();
Console.ReadLine();
}
}
C#このテンプレートをベースにして、
Studentクラスで「点数は 0〜100 に制限する」Bookクラスで「ページ数は 1 以上にする」Userクラスで「ユーザー名は空文字を禁止する」
など、いろいろな「ルール付きプロパティ」を試してみると、 フィールドとプロパティの役割がぐっと実感しやすくなります。
Day 32 のまとめ
Day 32 では、
- フィールド:クラスの中の「素のデータ置き場」
- プロパティ:フィールドへの「賢い出入り口」
get:読み取りの窓口set:書き込みの窓口(valueをチェックできる)- 自動実装プロパティ:シンプルなプロパティを楽に書くためのショートカット
という流れで、 「クラスの中のデータをどう扱うか」という基礎を押さえました。
これから先、
- カプセル化(情報を隠す)
- クラス設計のベストプラクティス
- より複雑なオブジェクト同士の関係
に進んでいくとき、 今日学んだ フィールドとプロパティの使い分け は、ずっとついて回る大事なテーマです。
ぜひ、
- 自分でクラスを 1 つ考えて、フィールド+プロパティを設計してみる
- 「どのデータは厳しくチェックしたいか」「どのデータはそのままでいいか」を考えてみる
- 自動実装プロパティと通常のプロパティを使い分けてみる
といった練習を通して、 オブジェクト指向の「クラス設計」が、少しずつ自分のものになっていく感覚を味わっていただければと思います。
