この記事ではクラスに設定する「プロパティ」と呼ばれるものを学んでいきます。プロパティ(英: property)は一般的に、「物体の特性・特質を意味する言葉」として知られていますが、この概念は現代プログラミングで重要です。
プロパティとは
プロパティとは一般的には以下の用語として解説されています。知らない単語がたくさん出てくるので、「ふ~ん」程度で知っておいてもらえれば十分かなと思います。
プロパティ (英: property) はオブジェクト指向プログラミング言語において、フィールドアクセスのカプセル化を実現するための言語機能および構文の一種である。
超簡単に意訳すると「クラス内の変数に対して、直接のアクセスをさせないために制御する仕組みである」かなと思っています。厳密にやりすぎても分からないだけなので。実際のプロパティはC#で以下のように記述します。本当はもっとありますが、簡略版で紹介しています。
public class Person
{
public string Name { get; set; }
}
これまではクラスの変数は「public string Name;」のように書いていました。「【C#】クラスにメソッドを定義して使用する方法」の最後の方で「publicメソッドにするのは「できる限り少なくする」のがお作法だと覚えておきましょう。」と書いています。これは変数にもいえることです。
public class Person
{
public string Name;
}
それじゃあ、クラスの外から、その要素にアクセスするにはどうすればいいの?と思うと思います。それを実現するために「プロパティがある」と考えてもらえればOKです。
プロパティとフィールド
プロパティについて学ぶには「フィールド」と呼ばれるものと区別をつける必要がありますので、まずは「プロパティ」と「フィールド」について解説しておきます。
これまでのクラスの学習では「変数」と言っていましたが、これは正確には「フィールド」と呼ばれています。クラス内部の構成要素として宣言された変数であり、「メンバ」・「メンバ変数」ともいわれています。クラス内部で格納・保持できる「データ」を指します。
public class Person
{
public string Name;
private int age;
}
それに対して、「プロパティ」はクラス内(オブジェクト内)にあるフィールドの値を取得・設定するための手段になります。クラスの内部からと外側からでは動きが違うようにみることもできます。
- クラスの外側から見ると「メンバ変数」のようにみえる
- クラスの内部から見ると「メソッド」のようにみえる
プロパティを介して、そのクラスのメンバ変数にアクセスできるため「アクセサー(accessor)」とも呼ばれています。プロパティは外部と内部のやり取りをする制御機能と覚えておきましょう。
プロパティを書く方法
「プロパティ」と「フィールド(メンバ変数)」は違う、という話をしました。ここではプロパティを定義する方法を解説すると同時に、フィールドへのアクセス方法やお作法の話もしていきます。
それでは新規のコンソールアプリケーションを作成して、以下のコードを記述してみましょう。少し長いソースになっていますが、分割して解説していこうと思います。
using System;
namespace App01
{
class Program
{
static void Main(string[] args)
{
//インスタンス化して名前を設定する
Person person = new Person();
person.Name = "Taro";
//名前を表示する
person.WriteName();
string name = person.Name;
Console.WriteLine("プロパティから取得:" + name);
Console.ReadLine();
}
//人間クラス
public class Person
{
//名前のプロパティ
public string Name
{
get { return _name; }
set { _name = value; }
}
//名前のフィールド(メンバ変数)
private string _name;
//publicメソッド
public void WriteName()
{
string msg = GetMessage();
Console.WriteLine(msg);
}
//privateメソッド
private string GetMessage()
{
return "Hello, " + _name;
}
}
}
}
書けましたでしょうか。画面に「Hello, Taro」と表示されていれば完成しています。それでは少しづつ解説していきます。
プロパティ
上記のソースにてプロパティを定義している箇所は以下になります。先ほどの説明とは少し違った書き方をしていますが、より正式な書き方はこちらになります。
//名前のプロパティ
public string Name
{
get { return _name; }
set { _name = value; }
}
もともとプロパティは「メンバ変数へのアクセス」を提供するものですので、メンバ変数である「フィールド」も一緒に定義しています。フィールド名は「_name」としており、プロパティの先頭を小文字にして、さらに「 _ 」を付けるのが一般的なようです。
person.Name = "Taro";
Personクラスのインスタンス・personに対する上記の処理により、Nameプロパティの「set」の処理が実行されます。「set { _name = value; }」の記述の「value」部分が「Taro」の値になっています。この「value」は必ず「value」と記述する必要があります。そして、そのvalueの値が「_name」に格納されます。
var name = person.Name;
その続きにある処理では、personインスタンスのNameプロパティの「get」の処理から値を取得して変数・nameに値を設定しています。「get { return _name; }」としており、getの処理が起動したら「_name」というフィールドの値を返却するようにしています。
プロパティを定義する場合は、フィールドも併せて定義するのが一般的になるので、覚えておくと便利です。getとsetがわからなくなってしまう時は「外からgetする = 外側からプロパティの値を取得する」「外からsetする = 外側からプロパティの値を設定する」と覚えておきましょう。
//名前のプロパティ
public string Name
{
get { return _name; }
set
{
if(value.Length >= 3)
{
_name = value;
}
}
}
また、プロパティ内には処理を記述することができます。setに対して3文字以上という制約を設けてみました。また、getに処理を記述する場合は、必ず「return」して値を返すようにする必要があります。
また、C#では「アロー演算子」を使用してプロパティを記述することもできます。アロー演算子はちゃんと解説しないので、これは話半分程度で聞いておいてもらえれば十分です。
//名前のプロパティ
public string Name
{
get => _name;
set => _name = value;
}
基本は以下の、一般的な方式で書けるようにすれば十分です。この基本は忘れないようにしておきましょう。
//名前のプロパティ
public string Name
{
get { return _name; }
set { _name = value; }
}
ということで、プロパティについてのお話は完了です。プロパティとフィールドはセットで覚えておいたほうが楽ですし、プロパティを使う実装が一般的ですので、今日の内容は非常に重要です。
プロパティはメンバへのアクセスを提供
この記事ではプロパティについて学習してきました。プロパティはクラス内部のメンバ変数に対する「アクセス」を提供する機能です。この考え方は「オブジェクト指向」への入口にもなる重要な役割を担っています。
プロパティは、クラス内のデータである「フィールド(メンバ変数)」と一緒に定義されることが多く、一緒になって使用されるので書き方も覚えておく必要があります。様々な記述方法がありますが、最もポピュラーな記述方法を押さえておきましょう。
さて、ここまで学習してクラスはほとんど完了です。次回はクラスを構成する要素について、総復習をしていきたいと考えています。クラスに関する学習もほとんど終盤に差し掛かりました。