プライベートメンバー
クラス内部から呼び出すことのできるプロパティ、メソッドの総称。
プライベートメンバーの対にパブリックメンバーが存在するが、これはクラス内外から自由に呼び出しすることが可能なプロパティ、メソッドのこと。プライベートメンバーはクラスの内部からしか呼び出せないように制限することで保守性が高める目的があるそうです。
参考 : https://tomoprog.hatenablog.com/entry/2018/08/19/114223
下記がコード例です。
_base
と_height
というプライベートなプロパティと_checkArgs
というプライベートなメソッドを持つTriangle
クラスを定義しています。※Triangle
クラスをfunction命令で定義していますがclass
で定義することも可能です。詳細は省きますがclass
定義はただのシンタックスシュガーなのでここではfunction命令で定義します。
function Triangle(){
// private プロパティ
let _base;
let _height;
// private メソッド
let _checkArgs = function(val){
return (typeof val === 'number' && val > 0);
}
// => privateメンバは this._base のようには書かない => 外部から直接代入できてしまう。
// => privateメンバはインスタンスが存在する間は内部にずっと存在する。
// 以下、privateメンバにアクセスするためのメソッド
// 特権メンバとも言う。これらは外部から直接呼び出して使える。
// つまりprivateメンバにアクセスしたい時には特権メンバを経由する必要がある。
this.setBase = function(base){
if (_checkArgs(base)) {
_base = base;
}
}
this.getBase = function(){
return _base;
}
this.setHeight = function(height){
if (_checkArgs(height)) {
_height = height;
}
}
this.getHeight = function(){
return _height;
}
}
コメントアウトにも書いてありますがプライベートなメンバーにアクセスするためにはこのクス内に定義されているアクセサーメソッドを経由する必要があります。
これらのアクセさーメソッドのことを特権メソッドというそうです。
実験
では、クラスの外部から直接アクセスが本当にできないのか見てみましょう。
まず、上記のTriangle
クラスを使ってgetArea
メソッドを追加しました。
メソッドの中身をみてもらえると分かりますがアクセサーメソッドを使ってプライベートメンバにアクセスしています。
function Triangle(){
let _base;
let _height;
let _checkArgs = function(val){
return (typeof val === 'number' && val > 0);
}
this.setBase = function(base){
if (_checkArgs(base)) {
_base = base;
}
}
this.getBase = function(){
return _base;
}
this.setHeight = function(height){
if (_checkArgs(height)) {
_height = height;
}
}
this.getHeight = function(){
return _height;
}
}
// privateメンバに(直接は)アクセスしない普通のメソッドを定義
Triangle.prototype = {
getArea : function(){
// 同じクラス内のアクセサーメソッドを使用
return this.getBase() * this.getHeight() / 2;
}
}
上記のクラスに対し下記の呼び出しを行います。
// インスタンス t を生成
let t1 = new Triangle();
// インスタンスに対して外部から直接、privateメンバにアクセスしようとしている。
t1._base = 10;
t1._height = 10;
console.log('1.三角形の面積:' + t1.getArea()); // NaN
t1.setBase(10);
t1.setHeight(10);
console.log('1.三角形の面積:' + t1.getArea()); // 50
t1._base = 10
、t1._height = 10
と記述しメンバに直接10を代入しようとしていますがこのまま、t1.getArea()
を呼び出しても期待値を出力することができません。
逆に今度はt1.setBase(10)
、t1.setHeight(10)
でアクセサーを使用してセットするとt1.getArea()
で期待値50を出力することができました。
一応、下記のパターンでも試します。
let t2 = new Triangle();
// privateプロパティにアクセスするメソッドを使用する。
t2.setBase(10);
t2.setHeight(10);
// アクセサーメソッド
console.log('2.三角形の面積:' + t2.getBase()); // 10
console.log('2.三角形の面積:' + t2.getHeight()); // 10
let t3 = new Triangle();
// privateプロパティに直接代入
t3._base = 10;
t3._height = 10;
console.log('3.三角形の面積:' + t3.getBase()); // undefined
console.log('3.三角形の面積:' + t3.getHeight()); // undefined
t2とt3を比べてもらうと分かりますがアクセサーを使ってセットしたt2の場合、getterでセットした値を再度取得できています。t3の場合は直接、代入した結果、getterで取得しようとしてもundefined
が帰ってきました。
これでprivateなメンバに対してはアクセさーを使わないとアクセスできないことを確認することができました。