JavaScriptにはpublic
やprivate
等の概念は無いですがやはり、private
相当の属性にはgetterやsetterを提供してやりたくなります。
余談ですが、プラべーメンバーの隠蔽はコンストラクター内でクロージャーを使用すれば実現可能ですが他のメンバー関数からも
直接参照出来なくなるので好みではありません(命名規則などのルールで拘束すれば十分だと思ってます)。
で、getterやsetterの実装を考えると高級言語によくあるpropertyは良くできた仕様です。
内部的にsetterを定義しないかreadonly
を宣言すれば参照のみ出来るメンバー変数のできあがりです。
[C#] { private int foo_; property int foo { get { return foo_; } };
getter,setterの実装をどうするか考えた結果、採用(別に私のオリジナルではありません)したのが以下の方法です。
Class = function() { this._foo = 0; } //privateメンバーは'_'で始める
Class.prototype.foo = function (value) {
if(!arguments.length) {
return this._foo;
} else {
this._foo = value;
}
}
実用上これで問題ないですが、.Net Framework のPropertyGridやXmlSerializerを実装しようとすると機械的にgetter,setterの
有無を確認できる方が都合が良いです。かといって getFoo() 等にするのは嫌・・・。
で、あいだととってgetter,setterをプライベート相当で定義することにします。
Class.prototype.__foo = {}
Class.prototype.__foo.get = function() {
return this._foo;
}
Class.prototype.foo = function (value) {
if(!arguments.length) {
return this.__foo.get();
} else {
this.__foo.set(value); //エラー処理は割愛
}
}
まあ、これを一つ一つ書くのは面倒なので関数を用意します。
function __property__(object, name, get, set, def) { var _nm = "_" + name; var __nm = "__" + name; object.prototype[_nm] = def || false; object.prototype[__nm] = { 'get': get, 'set': set }; return function (value) { if (!arguments.length) { !this[__nm].get && throw new Error('has not getter'); return this[__nm].get.apply(this); } else { !this[__nm].set && throw new Error('has not setter'); this[__nm].set.apply(this, arguments); } }; } Class.prototype.foo = __property__( Class, "foo", function() { return this._foo; }, null , "hoge");
・・・やり過ぎかなorz