プロパティ

 VC#では、クラスの中にプロパティを定義することができます。このプロパティは、クラス作成者の側から見ると、メソッドのように記述をします。クラス利用者の側から見ると、フィールドのように利用できます。

プロパティのイメージ
プロパティのイメージ

プロパティ定義の書式
アクセス修飾子 データ型 プロパティ名
{
 set
 {
  フィールド設定の記述
 }
 get
 {
  フィールド取得の記述
 }
}

 プロパティではsetアクセサーとgetアクセサーを指定します。setアクセサーは値を設定することができます。その際、valueキーワードに設定する値が渡されるので、そのキーワードを使って処理を記述します。setアクセサーのみ定義すると設定のみできるプロパティ、getアクセサーのみ定義すると参照のみできるプロパティ、両方とも指定すると参照・設定できるプロパティとなります。

○ プロジェクト

 プロジェクトを作成して確認してみましょう。

プロジェクトの種類 コンソール アプリケーション
プロジェクト名 PropertyTest

サンプルダウンロード

○ 作成の準備

 Carクラスにプロパティを追加しましょう。「ConstractorTest」をコピーしてプロジェクトを作成してください。

○ プログラム

 次のように記述を追加・修正してください。

Car.cs

  1. class Car
  2. {
  3.  //フィールド==========
  4.  private int speed;  //スピード
  5.  private double gas;  //ガソリン情報
  6.  //プロパティ==========
  7.  //スピード参照用
  8.  public int Speed
  9.  {
  10.   get
  11.   {
  12.    return this.speed;
  13.   }
  14.  }
  15.  //ガソリン参照・設定用
  16.  public double Gas
  17.  {
  18.   set
  19.   {
  20.    //止まっている場合は指定したガソリン量を給油
  21.    if (this.speed == 0)
  22.    {
  23.     this.gas += value;
  24.    }
  25.   }
  26.   get
  27.   {
  28.    return this.gas;
  29.   }
  30.  }
  31.  //コンストラクター==========
  32.  public Car() : this(20)
  33.  {
  34.  }
  35.  public Car(double gas)
  36.  {
  37.   this.speed = 0;
  38.   this.gas = gas;
  39.  }
  40.  //メソッド==========
  41.  //加速させるメソッド
  42.  public void SpeedUp(int sp)
  43.  {
  44.   //ガソリンを減らす
  45.   this.gas -= sp / 10.0;
  46.   if(this.gas < 0)  //ガソリンがマイナスになる場合
  47.   {
  48.    //ガソリンを0に補正し、スピードを増やさない
  49.    this.gas = 0;
  50.   }
  51.   else
  52.   {
  53.    //スピードを増やす
  54.    this.speed += sp;
  55.   }
  56.  }
  57.  //減速させるメソッド
  58.  public void SpeedDown(int sp)
  59.  {
  60.   //スピードを減らす
  61.   this.speed -= sp;
  62.   if(this.speed < 0) //スピードがマイナスになる場合
  63.   {
  64.    //スピードを0に補正する
  65.    this.speed = 0;
  66.   }
  67.  }
  68.  ////スピードを取得する
  69.  //public int GetSpeed()
  70.  //{
  71.  //  return this.speed;
  72.  //}
  73.  ////ガソリン量を取得する
  74.  //public double GetGas()
  75.  //{
  76.  //  return this.gas;
  77.  //}
  78.  ////ガソリンを給油するメソッド
  79.  //public void SetGas()
  80.  //{
  81.  //  //オーバーロードしているメソッドを呼び出す
  82.  //  this.SetGas(20);
  83.  //}
  84.  //public void SetGas(double gas)
  85.  //{
  86.  //  //止まっている場合は指定したガソリン量を給油
  87.  //  if (this.speed == 0)
  88.  //  {
  89.  //   this.gas += gas;
  90.  //  }
  91.  //}
  92. }

○ クラス図

○ 解説

 17~23行目では、スピード参照用のプロパティを定義しています。利用するプログラム側で「オブジェクト変数名.Speed」と記述することにより、getアクセサーで記述されている処理を実行します。今回は、speedフィールド変数の内容を返します。

 26~40行目では、ガソリン量の参照・設定用のプロパティを定義しています。利用するプログラム側で「オブジェクト変数名.Gas」と記述することにより、getアクセサーで記述されている処理を実行します。今回は、gasフィールド変数の内容を返します。また利用するプログラム側で「オブジェクト変数名.Gas = 30.5」と記述することにより、setアクセサーで記述されている処理を実行します。代入されたデータはvalueキーワードで扱えるので、車が止まっている場合はgasフィールド変数に設定するガソリン量を加算します。

 スピード参照、ガソリン量参照・設定のプロパティを用意したので、同じような処理をするメソッドはコメントアウトして廃止しました。

○ プログラム

 プロパティが用意されたので、Carクラスを利用する記述も変更しましょう。

Program.cs

  1. class Program
  2. {
  3.  //車の状態を表示するメソッド
  4.  static void ShowData(Car car)
  5.  {
  6.   //Console.WriteLine("スピード:{0}km", car.GetSpeed());
  7.   Console.WriteLine("スピード:{0}km", car.Speed);
  8.   //Console.WriteLine("ガソリン:{0}L", car.GetGas());
  9.   Console.WriteLine("ガソリン:{0}L", car.Gas);
  10.  }
  11.  static void Main(string[] args)
  12.  {
  13.   //インスタンスを生成する
  14.   Car car = new Car(40);
  15.   //現在の状態を表示する
  16.   ShowData(car);
  17.   while (true)
  18.   {
  19.    //操作を入力
  20.    Console.Write("1)加速 2)減速 3)給油 9)終了:");
  21.    string inputdata = Console.ReadLine();
  22.    //操作によって分岐する
  23.    switch (inputdata)
  24.    {
  25.     case "1":
  26.      //加速する
  27.      car.SpeedUp(5);
  28.      ShowData(car);
  29.      break;
  30.     case "2":
  31.      //減速する
  32.      car.SpeedDown(5);
  33.      ShowData(car);
  34.      break;
  35.     case "3":
  36.     //給油する
  37.     //car.SetGas(35);
  38.     car.Gas = 35;
  39.      ShowData(car);
  40.      break;
  41.     case "9":
  42.      //プログラムを終了する
  43.      return;
  44.    }
  45.   }
  46.  }
  47. }

○ 解説

 14、17、50行目は、メソッドの廃止により使えなくなったのでコメントアウトしました。その代わりに用意されたプロパティを利用するために、15、18行目はプロパティの参照の記述をしています。また、51行目でもメソッドによってガソリン量を設定していましたが、プロパティの代入によってガソリン量を設定する記述を追加しました。

 このようにプロパティを追加することにより、Carオブジェクトにとってはメソッドのように動作し、Carクラスを利用するオブジェクトからはフィールドを使うかのように利用することができるようになりました。

 また、プロパティを定義することでフィールドの定義を省略することができます。

○ プロジェクト

 プロジェクトを作成して確認してみましょう。

プロジェクトの種類 コンソール アプリケーション
プロジェクト名 PropertyTest2

サンプルダウンロード

○ プログラム

 Fruitクラスを追加して次のように定義してください。

Fruit.cs

  1. class Fruit
  2. {
  3.  //プロパティ
  4.  public string Name { get; private set; }
  5.  public int Price { get; set; }
  6.  //コンストラクタ
  7.  public Fruit(string name)
  8.   :this(name, 0)
  9.  {
  10.  }
  11.  public Fruit(string name, int price)
  12.  {
  13.   this.Name = name;
  14.   this.Price = price;
  15.  }
  16.  //メソッド
  17.  //個数を受け取って合計金額を計算するメソッド
  18.  public int CalculatePrice(int quantity)
  19.  {
  20.   return this.Price * quantity;
  21.  }
  22. }

○ クラス図

○ 解説

 今回のサンプルでのFruitクラスは、名前と価格の情報を持ち、個数を指定すると価格を元に合計金額を計算するメソッドを定義しています。

 12、13行目ではプロパティを定義しています。フィールドは定義していません。このようにプロパティのみ定義することでそれに対応するフィールドは自動的に用意されます。フィールドに対する参照や設定が単純なものは今回のように自動実装のプロパティで用意することができます。

 12行目にあるように、アクセサーに対してアクセス修飾子を指定することができます。今回のようにprivateを指定したsetアクセサーは、Fruitクラス内部からは利用できます。つまり、内部のコンストラクタやメソッドからであれば果物名を設定することができます。Fruitクラスを利用するクラスからは参照はできますが、設定はできません。

○ プログラム

 Fruitクラスを利用するプログラムを記述してください。

Program.cs

  1. static void Main(string[] args)
  2. {
  3. //フルーツオブジェクト生成
  4. Fruit fruit = new Fruit("りんご", 150);
  5. //りんごの合計金額を取得
  6. int totalprice = fruit.CalculatePrice(5);
  7. //りんごの合計金額を表示
  8. Console.WriteLine("合計金額:{0}円", totalprice);
  9. Console.ReadLine();
  10. }

○ 解説

 Fruitオブジェクトを生成して利用しています。今回はプログラムの中で指定していませんが、FruitオブジェクトのNameプロパティに代入する記述をするとエラーとなります。

○ 実行結果

合計金額:750円

前へ   次へ