気持ち悪いカプセル化

以前、自分用ライブラリとして使いたい型の話を書きました。
例として出したクラスはひどいものですが、
まあそれはいいとして、今回は「オブジェクト指向」の話です。


参考:Wikipedia
オブジェクト指向
カプセル化


オブジェクト指向という考え方の中に、「カプセル化」というものがあり、
どういう機能かさえ分れば中身なんてどうでもいいし、勝手に中身にアクセスしたり変更したりはさせん!
という考え方だと思っています。


要点は上の「型」っぽいクラスで、今回は元々用意されているPointクラスで考えてみます。
Pointクラスはシンプルに位置を示すものとして使えます。

var p:Point = new Point();
p.x = 10;
p.y = 20;
var objX:Number = p.x;
var objY:Number = p.y;

上の例のように、プロパティであるx, yに対して値を変更したり取得することもできます。


次に一つクラスを作ってみます。

package
{
    import flash.geom.Point;

    public class TestClass
    {
        private var _p:Point;    // ポイント

        public function TestClass()
        {
            _p = new Point();
        }

        // ポイント取得メソッド
        public function get p():Point { return _p; }
    }
}

このクラスの仕様として、ポイントのx, yの値は変更できないということにします。


で、実際にこのクラスを使ってみます。

var test:TestClass = new TestClass();

test.p.x = 10;    // ←!?

ポイントのx, yの値は変更できないようにしたいのに、普通に値を変更することができました。
つまり今回のこのTestClassは、「カプセル化」出来ていないということでしょうか...。


これを防ぐためにはポイント取得メソッドは消して、

public function get px():Number { return _p.x; }
public function get py():Number { return _p.y; }

といったように各自作らなければならないようです。
これなら最初から_pなんて定義せず、

private var _px:Number;
private var _py:Number;

とした方がいいのかもしれません。




今回もまた当たり前な話をした雰囲気ですが、
一時、僕は上のポイント取得メソッドみたいなものを平然と作っていた時期がありました。
相変わらず色々寄り道をしている感じです。




追記:
しかし上のようなポイント取得メソッドも、
Pointの代わりにShapeやらSpriteやらを取得する必要もあったりして、
Shapeのwidthやheightをいじることも可能だったり...。
カプセル化ってものを徹底するのにもある程度限界があるようですね...。