読者です 読者をやめる 読者になる 読者になる

白猫のメモ帳

JavaとかJavaScriptとかHTMLとか機械学習とか。

Java使いがC#を勉強する その③ プロパティ

こんばんは。

スマホの液晶シートが上手に貼れない私です。
今日はプロパティについてみていきます。

アクセサ


オブジェクト指向プログラミングでは、オブジェクト内部のメンバ変数に外部からアクセスするためには、
「アクセサ」と呼ばれるメソッドを利用します。

public class Hoge {

  private String piyo;

  public void setPiyo(String piyo) {
    this.piyo = piyo;
  }

  public String getPiyo() {
    return piyo;
  }
}

Hoge hoge = new Hoge();
hoge.setPiyo("ぴよぴよ");


ただ、この場合だとメンバ変数をpublicにしても特に何かが変わるわけではありません。
どちらかというと、メンバ変数に対するインタフェースを提供するみたいなイメージで考えるとしっくりきます。

getterで末尾に勝手に文字列を追加するとか、
メンバ変数を外から見たときの振る舞いを書くことができます。

public class Hoge {

  private int price;

  public void setPrice(int price) {
    this.price = price;
  }

  public String getPrice() {
    return price + "万円";
  }
}

Hoge hoge = new Hoge();

hoge.setPrice(5);
System.out.println(hoge.getPrice()); // 5万円


単なるsetterとgetterを自動生成したいだけならば、
JavaではLombokなどのライブラリを使うことが多いですね。

@Data
public class Hoge {
  private String piyo;
}


プロパティ


C#にあってJavaにない機能に「プロパティ」というものがあります。

public class Hoge
{
  private string _piyo;

  public string Piyo
  {
    get { return _piyo; }
    set { _piyo = value; } // valueという名前でアクセスできる
  }
}


フィールドに直接アクセスしているように見えますが、
ちゃんとアクセサを経由してデータのやり取りがされています。

Hoge hoge = new Hoge();
hoge.Piyo = "ぴよぴよ";


単なるgetterとsetterなら簡潔に書くことができます。
メンバ変数の宣言とアクセサが合体したような構文ですね。

public class Hoge
{
  public string Piyo { get; set; }
}


C#6.0からは初期化も同時にできるらしいです。
なんかこの構文すごく違和感を感じるのですが・・・。

public class Hoge
{
  public string Piyo { get; set; } = "ぴよぴよ";
}


getのみの定義も可能ですが、setのみの定義は不可です。
さらに、getのみの場合には式の結果を返すプロパティを作ることができます。

public class Hoge
{
  public string Huga { get; };
  public string Piyo { get; };

  public string HugaPiyo => Huga + Piyo;

  public Hoge(string huga, string piyo)
  {    
    this.Huga = huga;
    this.Piyo = piyo;
  }
}


ところで、setのオーバーロードをしたい場合にはプロパティは使えないのでしょうか?
こっちだけsetterメソッド経由ってなんか嫌だなぁ。

public class Hoge
{
  public string Piyo { get; set; }

  public void SetPiyo(int i)
  {
    this.Piyo = i.ToString();  // C#はプリミティブもObjectのサブクラスだからtoString使える!
  }
}

うーん。

Hoge hoge = new Hoge();
hoge.Piyo = "ぴよぴよ";
hoge.SetPiyo(3);


あと、getterは「get;」だけ書いて、setterはロジック書くとかダメなんですかね。

不安


言語仕様にこういうのが組み込まれているのはなかなかに素敵ですが、
パブリックフィールドアクセスしている気がして不安です。

早く慣れよう。