JavaScriptのクラスは、オブジェクト指向プログラミングを扱うための構文です。

前回は、オブジェクト指向の基となるクラスの定義方法やインスタンス化について解説しました。
今回は、インスタンスメソッドとアクセッサプロパティを使用したクラスの活用方法を見ていきましょう。

インスタンスメソッド

クラスの動作を定義するためのメソッドをインスタンスメソッドと呼びます。また、プロトタイプメソッドとも呼ばれることがあります。

インスタンスメソッドは、クラスのインスタンスに対して自由に定義することができるメソッドで、名前の通りインスタンスを通じて呼び出します。
クラスの中に任意のメソッドを作成し、コンストラクタメソッドと同様にthisを使います。

// クラスを定義
class Classname {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  // インスタンスメソッドを定義
  method(z) {
    this.z = z;
  }
}

// インスタンス化
const instance = new Classname('x', 'y');

// インスタンスメソッドを実行
instance.method('z');
console.log(instance.x, instance.y, instance.z) // "x", "y", "z"

インスタンスメソッドを使うと、各インスタンスが持つ動きを決めることができます。

インスタンスメソッドは、key : valueのようにオブジェクトの書き方でメソッドを定義することができないため、注意が必要です。

もう少し具体的な例を見てみましょう。
以下は、HealthCheckというクラスを使用した例です。

class HealthCheck {
  constructor(place, date) {
    this.place = place;
    this.date = date;
  }
  register(person) {
    this.person = person;
  }
}

const userInfo = new HealthCheck('ABC病院', '9月13日');
userInfo.register('山田花子');

console.log(userInfo.place, userInfo.date, userInfo.person); 
// "ABC病院", "9月13日", "山田花子"

健康診断を受診するために、registerというインスタンスメソッドを作成しています。
その中には、受診する人を登録するためのプロパティが用意されています。

このようにインスタンスメソッドは、クラスの各インスタンスの間で共有できることが特徴です。

プライベートとカプセル化

外部からアクセスして欲しくないメソッドやプロパティのことをプライベートメソッド(またはプロパティ)と呼びます。

他のオブジェクト指向言語には、外部からアクセスできないようにするためのプライベートという概念がありますが、現時点ではJavaScriptにはそのような概念がありません。
そのため、JavaScriptではクラスの外部から読み書きされたくないメソッドやプロパティの前に、_を使用してプライベートを表現しています。

class Classname {
  constructor(x, y) {
    this._x = x;
    this._y = y;
  }

  _method() {
    ...
  }
}

クラスの外部からアクセスする必要のない情報(メソッドやプロパティ)を隠すことをカプセル化と呼びます。

しかし、厳密には外部からのアクセスはできてしまうため、プライベートを表現する慣習であるということを覚えておくと良いでしょう。

class Classname {
  constructor(x, y) {
    this.x = x;
    this._y = y;
  }

  _method(z) {
    this._z = z;
  }
}

const instance = new Classname('パブリック' , 'プライベート');
instance._method('プライベート');
console.log(instance.x, instance._y, instance._z); 
// "パブリック", "プライベート", "プライベート"

JavaScriptでは、WeakSetという手法を使うことで外部からアクセスできなくなるプライベートを実現することができますが、この解説はまた別の記事で取り上げます。

アクセッサプロパティ

JavaScriptには、getterとsetterというメソッドが用意されており、これらをアクセッサプロパティと呼びます。
アクセッサプロパティは、メソッド名の前にgetまたはsetを記述して使用します。

getter

getterは、オブジェクトの持つプロパティを参照する場合に使われます。
getterを使う際には引数は必要ありませんが、必ず値を返すことが必要です。

class Classname {

  get method() {
    return 値;
  }
}
const instance = new Classname();
instance.method;

例えば、担任の先生の名字のみを返すgetterメソッドを定義するとこのようになります。

class Teacher {
  constructor(props) {
    this.name = props.name;
  }

// プロパティの値を返すgetter
  get lastName() {
    return this.name.split(' ')[0];
  }
}

const myTeacher = new Teacher({
  name: '山田 花子'
});

console.log(myTeacher.lastName); // "山田"

getterを通じてプロパティの値が返されます。
ここではthis.name.split('  ')によって、名前のスペースを基準に、名字と名前を2つの要素に分けています。
その後、[0]のように、1つ目の要素を返すことで名字を得ることが可能です。

setter

setterは、オブジェクトの持つプロパティを代入する場合に使われます。
setterを使う際は、引数を記述します。プロパティに代入された値がこの引数に入ります。
getterのように値を返す必要はありません。

class Classname {

  set method(引数) {
    処理;
  }
}
const instance = new Classname();
instance.method = 値;

担任の先生が変わったとして、名前をアップデートしてみましょう。

class Teacher {
  constructor(props) {
    this.name = props.name;
  }

  // プロパティの値を代入するsetter
  set newTeacher(newName) {
    this.name = newName;
  }
  // プロパティの値を返すgetter
  get newTeacher() {
    return this.name;
  }
}

const myTeacher = new Teacher({
  name: '山田 花子'
});

myTeacher.newTeacher = '田中 太郎'; // 値がsetterの引数に渡る
console.log(myTeacher.newTeacher); // "田中 太郎"

myTeacher.newTeacher = '田中 太郎'のように、新しく加えられた値がsetterの引数に渡っています。

setterはプロパティの参照には使用できないため、getterを使ってアップデートされたプロパティを参照しています。
getterの記述がない場合にプロパティ参照しようとすると、undefinedとなるため注意してください。

まとめ

今回は、クラスのインスタンスメソッドやアクセッサプロパティについて解説してきました。

クラスをインスタンス化するだけではアクションを起こすことができませんが、インスタンスメソッドを活用することで、各インスタンスの動作を定義することができます。
また、アクセッサプロパティを用いるとプロパティの参照や代入を効率的に行うことも可能です。

オブジェクトをより便利に操作することができるため、活用してみてください。

合わせて読みたいクラスシリーズ

第1回:オブジェクト指向とクラス
第2回:クラスとメソッド -インスタンスメソッド・アクセッサプロパティ(当記事)
第3回:クラスとメソッド -staticメソッド
第4回:クラスの継承