トップC# > プロパティおよびカプセル化

プロパティおよびカプセル化

プロパティとは

プログラミング言語におけるプロパティとは何か? Wikipediaの冒頭の一節[1]が簡潔で要を得ている。

プロパティ(property) はオブジェクト指向プログラミング言語において、フィールドアクセスのカプセル化を実現するための言語機能および構文の一種である。

これまで沢山のプログラミング言語を使ってきた。 Fortran、アセンブリ言語、JavaScript、C++、Python などは精々数年である。 期間が長いのは C、Java、C#である。

このため、プロパティは C# 特有かと思っていたが、Python にもあるようだ。 自分は趣味のプログラマーのため、これまで多くの言語に触れてきたが、同期間では2,3の言語であり、 他の言語の印象は薄れる。

1年ほど前までの6、7年は C# がメインであった。 その前は Java で、今また、Android スマホの地図アプリ開発に没頭している関係で、Javaがメインである。

カプセル化

オブジェクト指向言語では、クラスのメンバー変数(フィールド)を直接、操作するのは避けるべきとされている。

少々特殊であるが、目下の主テーマである地図システムを例にする。 位置は、経度、緯度で表すのが一般的である。 地図に表すには、メルカトル図法での世界地図では、 例えば、左上(西北端)を原点(0,0)、右下(東南端)を (1,1) とした 世界XY平面座標に変換する必要がある。

内部的に、極座標とするか、平面座標するかに関わらず、極座標でセットしたり、極座標を得たいときと 平面座標でセットしたり、平面座標を得たいときがある。

このようなとき、プロパティを使えば、内部的に、平面座標か極座標かを気にせず、 極座標でセットすることも、平面座標でセットすることができる。 また、極座標で取り出すことも、平面座標でとり出すこともできる。

内部的に、平面座標で、データを記憶するときは、次のようにする。 操作は p.lon = 123.456; のように、見かけ上 public なメンバー変数と同じように扱える。

この例では、コンストラクタは引数二つでは、極座標か平面座標かの区別がつかないため、 区別を示す、第三の引数が必要である。

class Point {
    private double _x;
    private double _y;

    public double x { set { _x = value; } get { return _x; } }
    public double y { set { _y = value; } get { return _y; } }

    public double lon { set { _x = Lon2X(value); } get { return X2Lon(_x); } }
    public double lat { set { _y = Lat2Y(value); } get { return Y2Lat(_y); } }
}

一方、内部的に極座標でデータを記憶する場合には次のようにする。

class Point {
    private double _lon;
    private double _lat;

    public double x { set { _lon = X2Lon(value); } get { return Lon2X(_lon); } }
    public double y { set { _lat = Y2Lat(value); } get { return Lat2Y(_lat); } }

    public double lon { set { _lon = value; } get { return _lon; } }
    public double lat { set { _lat = value; } get { return _lat; } }
}

通常の地図では、極座標の精度は小数点以下7桁で十分である。 この場合、10の7乗を掛けて整数化すれば int型(4バイト)で表現でき、double型に比べて、 メモリ使用量を半減できる。

class Point {
    private const double E7 = 10000000.0;
    private int _lon;
    private int _lat;

    public double x { set { _lon = (int)(X2Lon(value)*E7); } get { return Lon2X(_lon/E7); } }
    public double y { set { _lat = (int)(Y2Lat(value)*E7); } get { return Lat2Y(_lat/E7); } }

    public double lon { set { _lon = (int)(value*E7); } get { return _lon/E7; } }
    public double lat { set { _lat = (int)(value*E7); } get { return _lat/E7; } }
}

おわりに

Javaにはプロパティがない。カプセル化はメソッドを使うことになる。 見栄えが悪いので、自分しか使わないプログラムでは、パブリック メンバー変数を使うことが多い。 この場合、カプセル化されていないため、実装変更の柔軟性に欠ける。

要所では、メソッドを使わざるを得ないであろう。

リファレンス

[1] プロパティ (プログラミング)