CodeGym /コース /Frontend SELF JA /カプセル化

カプセル化

Frontend SELF JA
レベル 40 , レッスン 2
使用可能

9.1 基本的な概念

カプセル化は、オブジェクト指向プログラミング(OOP)のキーコンセプトの一つで、オブジェクトの内側の実装詳細を隠し、厳密に定義されたインターフェースを通じてそれらの詳細にアクセスできるようにするものだよ。これによってセキュリティが向上し、コード管理も簡単になるんだ。

カプセル化の利点:

  1. データの隠蔽: カプセル化は内側の実装詳細を隠して、必要なメソッドやプロパティだけにアクセスを提供することができるんだ。これにより、オブジェクトの誤った使用を防ぎ、コードの安全性を向上させるよ。
  2. アクセス制御: カプセル化により、データやメソッドへのアクセスを制御し、定義されたメソッドを通じてだけオブジェクトの内部状態を変更できるようにすることができるよ。
  3. メンテナンス性: カプセル化はコードのメンテナンスを向上させるんだ。実装に変更を加えても、クラスの外部インターフェースには影響を与えないからね。これにより、クラスを使用しているコードを変更することなく、実装を改善できるんだ。
  4. テストの向上: カプセル化はオブジェクトの内部実装を分離することで、モジュールテストを簡単にし、予期しない副作用の発生を減らすことができるんだ。

JavaScriptでは、カプセル化はメソッドとプロパティを使用して実現されるよ。ES2022からは、プライベートフィールドやメソッドも利用できるようになったんだ。

9.2 クロージャによるカプセル化

ES2022のプライベートフィールドの導入前は、JavaScriptでのカプセル化はよくクロージャを使って達成されていたんだ。

例:

  • 変数countは関数createCounterの内部でのみアクセス可能で、外部からはアクセスできないんだ。
  • メソッドincrementdecrementgetCountはプライベート変数countとやりとりできるんだ。
JavaScript
    
      function createCounter() {
        let count = 0; // プライベート変数

        return {
          increment() {
            count++;
            console.log(count);
          },
          decrement() {
            count--;
            console.log(count);
          },
          getCount() {
            return count;
          }
        };
      }

      const counter = createCounter();
      counter.increment(); // 1
      counter.increment(); // 2
      console.log(counter.getCount()); // 2
      counter.decrement(); // 1
    
  

9.3 ES2022のプライベートフィールド

ES2022では、#シンボルを使用してプライベートフィールドやメソッドを宣言できるようになったんだ。プライベートフィールドやメソッドはクラスの外部からアクセスしたり変更することはできないよ。

例:

  • プライベートフィールド#name#age#シンボルを使って宣言されているんだ。
  • メソッドgetNamegetAgesetNamesetAgeはプライベートフィールドとやりとりできるんだ。
  • クラスの外部からプライベートフィールドにアクセスしようとするとエラーになるよ。
JavaScript
    
      class Person {
        #name; // プライベートフィールド
        #age; // プライベートフィールド

        constructor(name, age) {
          this.#name = name;
          this.#age = age;
        }

        getName() {
          return this.#name;
        }

        getAge() {
          return this.#age;
        }

        setName(name) {
          this.#name = name;
        }

        setAge(age) {
          if (age > 0) {
            this.#age = age;
          }
        }
      }

      const person = new Person('Alice', 30);
      console.log(person.getName()); // "Alice"
      console.log(person.getAge()); // 30
      person.setName('Bob');
      person.setAge(25);
      console.log(person.getName()); // "Bob"
      console.log(person.getAge()); // 25
      
      console.log(person.#name); // エラー: プライベートフィールドにはアクセスできない
    
  

9.4 プライベートメソッド

プライベートメソッドも#シンボルを使って宣言できて、クラスの外からアクセスすることはできないんだ。

例:

  • プライベートフィールド#balanceとプライベートメソッド#logTransactionはオブジェクトBankAccountの状態を管理するために使われているよ。
  • プライベートメソッド#logTransactionは、depositwithdrawといった公開メソッド内で呼ばれて、トランザクションを記録するんだ。
JavaScript
    
      class BankAccount {
        #balance;

        constructor(initialBalance) {
          this.#balance = initialBalance;
        }

        deposit(amount) {
          if (amount > 0) {
            this.#balance += amount;
            this.#logTransaction('deposit', amount);
          }
        }

        withdraw(amount) {
          if (amount > 0 && amount <= this.#balance) {
            this.#balance -= amount;
            this.#logTransaction('withdraw', amount);
          }
        }

        getBalance() {
          return this.#balance;
        }

        #logTransaction(type, amount) {
          console.log(`Transaction: ${type} ${amount}`);
        }
      }

      const account = new BankAccount(1000);
      account.deposit(500); // "Transaction: deposit 500"
      console.log(account.getBalance()); // 1500
      account.withdraw(200); // "Transaction: withdraw 200"
      console.log(account.getBalance()); // 1300
      
      account.#logTransaction('test', 100); // エラー: プライベートメソッドにはアクセスできない
    
  
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION