カプセル化のためのプロパティ
CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 32/70。
プロパティは、C#でカプセル化を実装するための主要な手段です。フィールドを直接公開するのではなく、データへのアクセス方法や変更方法を制御するプロパティでフィールドをラップします。
このパターンでは、プライベートフィールドと、アクセサーに検証やロジックを含むパブリックプロパティを組み合わせます。
public class Temperature
{
private double celsius;
public double Celsius
{
get { return celsius; }
set
{
if (value < -273.15)
celsius = -273.15; // 絶対零度が下限
else
celsius = value;
}
}
}これで、外部のコードからあり得ない温度を設定できなくなります。このプロパティは門番として機能し、オブジェクトが常に有効な状態を保つようにします。これがカプセル化の実例です。内部データは保護されながらも、制御されたインターフェースを通じてアクセスできます。
プロパティを使って、値を計算したり副作用を発生させたりすることもできます。
public double Fahrenheit
{
get { return celsius * 9 / 5 + 32; }
set { celsius = (value - 32) * 5 / 9; }
}外部からは2つのプロパティが見えますが、内部にはフィールドが1つしかありません。プロパティを使うと、クラスを使用するコードを壊さずに実装の詳細を変更できます。これは適切なカプセル化の重要な利点です。
チャレンジ
簡単プロパティを使ってデータの整合性を保護する商品在庫システムを作りましょう。価格が負の値にならず、数量が常に有効な範囲内に保たれるクラスを作成します。プロパティがデータを守る門番としてどのように機能するかを確認しましょう。
コードを2つのファイルに分けて整理します。
Product.cs:Inventory名前空間に、プロパティによる検証を通じて商品情報を管理するProductクラスを作成します。商品には以下が必要です。- private フィールド
price(decimal)と、価格が決して0未満にならないようにする public プロパティPrice。負の価格を設定しようとした場合は、代わりに0として保存します。 - private フィールド
quantity(int)と、値を0から1000の範囲内に保つ public プロパティQuantity。0 未満の値は 0 に、1000 を超える値は 1000 になります。 - public の自動実装プロパティ
Name(string) Price * Quantityを返す、計算による読み取り専用プロパティTotalValue
- private フィールド
Program.cs: メインファイルで、入力値を使ってProductを作成します。次に、無効な可能性のある追加の入力値を使って、価格と数量の変更を試みます。プロパティがデータをどのように保護するかを確認できるよう、作成後と変更後の商品の状態を出力します。
入力は5つです。
- 商品名
- 初期価格(decimal)
- 初期数量(整数)
- 設定する新しい価格(decimal、負の値の場合があります)
- 設定する新しい数量(整数、範囲外の場合があります)
次の形式で出力します。
After creation:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
After modifications:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}たとえば、入力が Laptop、999.99、50、-100、1500 の場合、出力は次のようになります。
After creation:
Laptop: Price=999.99, Qty=50, Total=49999.50
After modifications:
Laptop: Price=0, Qty=1000, Total=0負の価格が 0 になり、数量の 1500 が 1000 に制限されたことに注目してください。プロパティが無効な状態からオブジェクトを守っています。これがカプセル化の働きです。
自分で試してみよう
using System;
using Inventory;
class Program
{
public static void Main(string[] args)
{
// 入力を読み取る
string name = Console.ReadLine();
decimal initialPrice = Convert.ToDecimal(Console.ReadLine());
int initialQuantity = Convert.ToInt32(Console.ReadLine());
decimal newPrice = Convert.ToDecimal(Console.ReadLine());
int newQuantity = Convert.ToInt32(Console.ReadLine());
// TODO: 初期値を使ってProductを作成する
// TODO: 作成後の製品の状態を出力する
Console.WriteLine("After creation:");
// 出力形式: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
// TODO: 新しい値で価格と数量を変更する
// TODO: 変更後の製品の状態を出力する
Console.WriteLine("After modifications:");
// 出力形式: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: C#オンラインコンパイラ