JavaScript | 第13章「クラスの使用」

javascrpit JavaScript
スポンサーリンク

JavaScript の クラス (class) を初心者向けに、なるべくわかりやすく説明します。全体像 → 各パーツ → 例 → 注意点、という流れで進めます。


全体像:クラスって何?なぜ使う?

  • JavaScript はもともと プロトタイプベース のオブジェクト指向言語で、「オブジェクトが別のオブジェクトを原型 (プロトタイプ) として参照して振る舞いを継承する」という仕組みがあります。
  • クラス構文は、そのプロトタイプ継承の考え方を、Java や C++ のように見える形で書けるようにした “糖衣構文 (syntactic sugar)” の一つ、という見方ができます。
  • クラスを使うと、「ある型(例えば「人間」「車」「色」など)」を定義し、その型に属する複数のインスタンス(実体)を簡単につくったり共通の処理をまとめたりできます。

例:class Person { … } と定義しておいて、new Person("Alice"), new Person("Bob") といった具合に複数の “人” を作る。

クラスの基本構成要素

以下がクラスを構成する主な要素です。

要素説明
クラス宣言 / クラス式class MyClass { … } で宣言する。式として変数に代入することも可能。class Color { … } または const C = class { … }
コンストラクター (constructor)インスタンスを生成するとき(new したとき)最初に実行される初期化処理を書く。プロパティを this に代入することが多い。constructor(r, g, b) { this.r = r; this.g = g; this.b = b; }
インスタンスメソッド各インスタンス(オブジェクト)が利用できるメソッド。プロトタイプに配置され、各インスタンスで共有される。getRed() { return this.r; }
フィールド(プロパティ)データを格納するための変数。パブリックフィールドプライベートフィールド の方法がある。myField = "foo";#myPrivate = 123;
アクセサ (getter / setter)プロパティに対して “まるで直接プロパティのように” 読み書きできるメソッドを書ける。get red() { return this.r; }set red(v) { this.r = v; }
静的メソッド / 静的プロパティインスタンスではなく「クラス自身」に属するメソッドやプロパティ。ユーティリティ的な機能などに使われる。static isValid(r,g,b) { … }
継承 (extends / super)あるクラスを拡張し、親クラスの機能を引き継ぎつつ新しい機能を追加できる。super(...) を使って親クラスの constructor を呼ぶ。class ColorWithAlpha extends Color { … }

具体例で見てみよう:Color クラス

以下のようなクラスを考えてみます。

class Color {
  // プライベートフィールド(インスタンス内部だけ使う)
  #values;

  constructor(r, g, b) {
    // 初期化
    this.#values = [r, g, b];
  }

  // インスタンスメソッド
  getRed() {
    return this.#values[0];
  }

  setRed(value) {
    if (value < 0 || value > 255) {
      throw new RangeError("Invalid R value");
    }
    this.#values[0] = value;
  }

  // アクセサ(プロパティ風に使える get / set)
  get red() {
    return this.#values[0];
  }
  set red(v) {
    if (v < 0 || v > 255) {
      throw new RangeError("Invalid R value");
    }
    this.#values[0] = v;
  }

  // 静的メソッド(クラス自身に属する)
  static isValid(r, g, b) {
    return [r, g, b].every(v => v >= 0 && v <= 255);
  }

  // 継承したクラスで toString を上書き(オーバーライド)できるような例
  toString() {
    return this.#values.join(", ");
  }
}
JavaScript

このクラスの使い方例:

const c = new Color(100, 150, 200);
console.log(c.getRed());     // 100
c.setRed(255);
console.log(c.red);          // 255(アクセサを使っても OK)

console.log(Color.isValid(0, 128, 255));  // true
console.log(c.toString());  // "255, 150, 200"
JavaScript

ポイント:

  • #values はプライベートなので、クラスの外から c.#values のようにアクセスするとエラーになる。
  • get red / set red を使うと、c.red = 50; のような見た目で書けるが、裏でバリデーション(0〜255チェックなど)を行える。
  • 静的メソッド isValid は、インスタンスを生成しなくても Color.isValid(...) で使える。

継承(サブクラス)の例

Color クラスを拡張して、アルファ値(透明度)を持つクラスを作る例:

class ColorWithAlpha extends Color {
  #alpha;

  constructor(r, g, b, a = 1) {
    // `super` を使って親クラス Color のコンストラクタを呼ぶ
    super(r, g, b);
    this.#alpha = a;
  }

  get alpha() {
    return this.#alpha;
  }
  set alpha(v) {
    if (v < 0 || v > 1) {
      throw new RangeError("Alpha must be between 0 and 1");
    }
    this.#alpha = v;
  }

  toString() {
    // 親クラスの toString を使いつつ、自分の alpha も追加
    return `${super.toString()}, ${this.#alpha}`;
  }

  // 静的メソッドをオーバーライドする例
  static isValid(r, g, b, a) {
    return super.isValid(r, g, b) && a >= 0 && a <= 1;
  }
}
JavaScript

こうすると、

const ca = new ColorWithAlpha(10, 20, 30, 0.5);
console.log(ca.red);        // 10(Color のプロパティも使える)
console.log(ca.alpha);      // 0.5
console.log(ca.toString()); // "10, 20, 30, 0.5"
console.log(ColorWithAlpha.isValid(255, 0, 0, 0.8)); // true
JavaScript

注意点:

  • 派生クラスのコンストラクタでは、this を使う前に super(...) を呼ぶ必要がある。
  • 派生クラスでも静的メソッドやプロパティは継承されるが、オーバーライドや拡張が可能。
  • 親クラスのプライベートフィールド (#values など) は、子クラス側から直接アクセスできない。

その他のポイント・注意点

  • クラス宣言は 巻き上げ (hoisting) されない(宣言より前に使おうとするとエラーになる)ので、クラスを宣言する前に new MyClass() などはできない。
  • new を使わずにクラスを呼び出すとエラーになる(クラスのコンストラクタは new 呼び出し必須)。
  • プロトタイプベースの継承を理解しておくと、クラスの背後でどう動いているかを理解しやすくなる(クラスはあくまで見かけを簡潔にする構文)。
  • 過度な継承階層は複雑さを招くので注意(設計をシンプルに保つことが重要)。
タイトルとURLをコピーしました