2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptのclass構文とOOP設計:継承・カプセル化・設計責務の使い分け

Posted at

概要

JavaScriptは元々プロトタイプベースの言語だが、ES6以降 class 構文が導入され、**クラスベースのOOP(オブジェクト指向プログラミング)**がより書きやすくなった。

しかし、構文をなぞるだけでは不十分。
「いつ class を使うべきか」「extends や super の設計責任は何か」など、設計レベルでの判断基準が必要となる。

この記事では、構文解説にとどまらず、クラス構文が担うべき責務とその正しい使い所を体系的に整理する。


対象環境

ES6 以降(Node.js / モダンブラウザ)

class構文の基本

class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    return `Hello, ${this.name}`;
  }
}

const u = new User('toto');
u.greet(); // Hello, toto

constructor:インスタンス初期化の入口

class Product {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}
  • ✅ 自動的に new で呼ばれる
  • ✅ インスタンス生成時に一度だけ実行される
  • return でオブジェクトを返すと、this は無効化される

extends / super:継承と親クラスへのアクセス

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    return `${this.name} makes a sound`;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 親のconstructorを呼び出す
    this.breed = breed;
  }

  speak() {
    return `${this.name} barks`;
  }
}

const d = new Dog('Max', 'Shiba');
d.speak(); // Max barks

✅ superとは

  • super() は親の constructor を呼び出す
  • メソッド内で super.method() によって親のメソッドを上書きしつつ呼び出すことも可能

クラス設計における責務の切り方

要素 担当すべき責務
constructor インスタンスの最小完全構成の定義
メソッド インスタンスに属する処理の提供
静的メソッド インスタンスに依存しない汎用処理
継承 インターフェースの統一 / 特化の分離

static:インスタンスを持たないクラスの関数群

class MathUtil {
  static double(x) {
    return x * 2;
  }
}

MathUtil.double(3); // 6
  • ✅ 状態を持たない「関数集合体」として使える
  • ❌ インスタンスとは分離されるため、状態にアクセスできない

getter / setter:アクセス制御と表現力の向上

class Rectangle {
  constructor(w, h) {
    this.w = w;
    this.h = h;
  }

  get area() {
    return this.w * this.h;
  }

  set width(val) {
    if (val < 0) throw new Error('Invalid width');
    this.w = val;
  }
}

const r = new Rectangle(3, 4);
console.log(r.area); // 12

抽象クラス風の使い方(JSには正式な抽象クラスはない)

class AbstractService {
  fetch() {
    throw new Error('must implement fetch()');
  }
}

class RealService extends AbstractService {
  fetch() {
    return 'real data';
  }
}

→ ✅ 設計上の“制約”として class を利用できる


よくある誤解

❌ 関数ベースと class ベースは同じ?

→ ✅ 振る舞いは似ているが、設計意図が異なる

  • 関数ベース:一時的な処理
  • クラスベース:構造と責任をもった永続的な振る舞い

class構文を使うべき設計条件

条件 class構文を使うべきか?
インスタンスごとに状態を持つ ✅ Yes
状態に基づいて動的な処理を行う ✅ Yes
汎用の関数群を定義したい ❌ No → functionで十分
状態不要 / 設計不要なデータ変換 ❌ No → モジュール関数へ

結語

JavaScriptのクラス構文は、「OOP風」な糖衣構文ではない。
それは 状態を伴う構造を明示し、再利用性と抽象性を担保する“設計のための記法” である。

  • 継承は、振る舞いを共通化するための道具
  • constructorは、最小責務を与えるための入口
  • メソッドは、状態の操作手段であり、機能の境界である

構文に振り回されるのではなく、設計に沿って構文を選ぶこと。
それがOOPにおけるクラスの、本来の意味である。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?