プロパティの考え方

2019年6月15日

プロパティは、利用側からはフィールドのように見えます。また、設定しているクラス内からはメソッドのように振舞います。フィールドにアクセスする窓口の役割をします。

プロパティを使わずにデータにアクセスする例

フィールドにアクセスする

using System;

class Program
{
    static void Main(string[] args)
    {
        // Dateクラス(日付)のインスタンス作成
        Date myDate = new Date();
        // フィールド(月)に10を書き込み
        myDate.month = 10;
        // フィールドから値を読み出してmyMonth変数に代入
        int myMonth = myDate.month;
        // 代入された内容を表示
        Console.WriteLine($"{myMonth} 月");
    }
}

class Date
{
    // 読み書きができるフィールド
    public int month = 1;
}

// 表示
// 10 月

メソッドでアクセスする

先ほどのコードは、うまく動作してそうです。
しかし、myDate.month = 13としてみるとどうでしょう?
結果は、13 月となりますね。これを防ぐために、Dateクラスの方で制限をかけると良さそうです。

Dateクラスに制限をかけることができるメソッド(12月までした入力を受け付けない)を作ってみましょう。

using System;

class Program
{
    static void Main(string[] args)
    {
        // Dateクラス(日付)のインスタンス作成
        Date myDate = new Date();
        // フィールド(月)に13を書き込み
        myDate.SetMonth(13);
        // フィールドから値を読み出してmyMonth変数に代入
        int myMonth = myDate.GetMonth();
        // 代入された内容を表示
        Console.WriteLine($"{myMonth} 月");
    }
}

class Date
{
    // 読み書きができないフィールド(プライベート)
    private int month = 1;

    //月がセットできるメソッド
    public void SetMonth(int month)
    {
        // もし、引数のmonthが12以下なら内部のmonthに代入する
        if (month <= 12)
        {
            this.month = month;
        }
    }
    // 月を読みだせるメソッド
    public int GetMonth()
    {
        // monthの値を呼び出し元に戻す
        return month;
    }
}

// 表示
// 1 月

プロパティでアクセスする

目的は達成できました。
13月は設定できないようになりましたね。
C#では、同じことをプロパティという機能で達成することができます。
特徴として、

  • アクセス側では、フィールドへ読み書きする手順と同じ
  • 今はアクセスに制約が必要ないときでも、将来の変更に備えることができる
  • C#のライブラリ(クラスの塊)でも多用されており、それらの理解にも役立つ
using System;

class Program
{
    static void Main(string[] args)
    {
        // Dateクラス(日付)のインスタンス作成
        Date myDate = new Date();
        // フィールド(月)に10を書き込み
        myDate.Month = 13;
        // フィールドから値を読み出してmyMonth変数に代入
        int myMonth = myDate.Month;
        // 代入された内容を表示
        Console.WriteLine($"{myMonth} 月");
    }
}

class Date
{
    // 読み書きができないフィールド(プライベート)
    private int month = 1;

    //月がセットできるメソッド
    public int Month
    {
        get
        {
            return month;
        }
        set
        {
            // もし、引数のmonthが12以下なら内部のmonthに代入する
            if (value <= 12)
            {
                month = value;
            }
        }
    }
}

// 表示
// 1 月
class Program
{
    static void Main(string[] args)
    {
        // インスタンスの作成
        Player falcon = new Player();
        // フィールドに10を書き込み
        falcon.hp = 10;
        // フィールドから値を読み出し
        int hpValue = falcon.hp;
        // 代入されたhpを読み出し
        Console.WriteLine(hpValue);
    }
}

class Player
{
    // クラス内のみ読み書きできるフィールド
    private int hp;
    // プロパティ
    public int Hp
    {
        // 読み出し(他のクラスからでも読み書き可能)
        get { return hp; }
        // 書き込み(他のクラスからでも読み書き可能)
        set { hp = value; }
    }

    // このように記述してもOK
    //  public int Hp { get => hp; set => hp = value; }
}

// 表示
// 10

自動プロパティ

  • アクセス側では、フィールドへ読み書きする手順と同じ
  • プロパティは、省略されている書き方
  • C#内部では、上記「プロパティでアクセスする」と同じコードになっている
  • 今はアクセスに制約がないときでも、将来の変更に備えることができる

自動プロパティでは private の変数にアクセスできません。
アクセスする必要がある時は、private のhpを作成する必要があります。

class Program
{
    static void Main(string[] args)
    {
        // インスタンスの作成
        Player falcon = new Player();
        // 書き込みメソッドで10をセット
        falcon.Hp = 10;
        // 読み出しメソッドから値を取得
        int hpValue = falcon.Hp;
        // hpを表示(読み込み)
        Console.WriteLine(hpValue);
    }
}

class Player
{
    // プロパティ(読み出し、書き込み)
    public int Hp { get; set; }
}

// 表示
// 10

書き込みに制約を持たせる

  • アクセス側では、フィールドへ読み書きする手順と同じ
  • プロパティは、private フィールドを設定

プロパティにしたことで、制約をかける必要が出てきた場合でもアクセス側の変更が不要です。

class Program
{
    static void Main(string[] args)
    {
        // インスタンスの作成
        Player falcon = new Player();
        // 書き込みメソッドで10をセット
        falcon.Hp = 10;
        // 読み出しメソッドから値を取得
        int hpValue = falcon.Hp;
        // hpを表示(読み込み)
        Console.WriteLine(hpValue);
    }
}

class Player
{
    private int hp;
    // プロパティ(読み出し、書き込み)
    public int Hp
    {
        get
        {
            return hp;
        }
        set
        {
            if (value > 0)
            {
                hp = value;
            };
        }
    }

    // 表示
    // 10
}

色々な自動プロパティ (C#3〜)

読み出し専用プロパティ(C#6〜)

  • アクセス側では、フィールドからの読み出しのみ可能
class Program
{
    static void Main(string[] args)
    {
        // インスタンスの作成
        Player falcon = new Player();
        // 書き込みメソッドで10をセット
        falcon.Hp = 10;
        // 読み出しメソッドから値を取得 => エラー
        int hpValue = falcon.Hp;
        // hpを表示(読み込み)
        Console.WriteLine(hpValue);
    }
}

class Player
{
    public int Hp { get; }
}

プロパティ初期化子(C#6〜)

  • 初期値の代入が可能
class Player
{
    public int Hp { get; } = 10;
}

C#

Posted by hidepon