💬

TypeScriptで理解するclass構文(private,public,readonly修飾子 初期化のショートカット)

2021/11/06に公開

前回の続き
https://zenn.dev/kimura141899/articles/4366fa6aeb5c3c

今回はprivate,public,readonly修飾子及びconstructor実行における初期化のショートカットについて。

private,public,readonly修飾子

private

外部からのアクセスを拒否するようにする為の修飾子。
クラスのメソッドなどの内部からのみアクセスできるようにする。

public

外部からのアクセスが可能になる。デフォルトではpublic修飾子が適用されている。

readonly

一度初期化したら書き直すことができなくする修飾子。読み取り専用。

外部からアクセスがあったり、上書きが発生すると思わぬ不具合が発生するものに関して、修飾子をつけることにより制御することができます。

class Foods {
 private readonly likeAndDislike:"好きな食べ物" | "嫌いな食べ物";//読み取り専用
  public genle:string;//外部アクセス可能
  private foodList: string[] = [];//外部アクセス不可
  
  //初期化
  constructor(likeAndDislike:"好きな食べ物" | "嫌いな食べ物",genle: string) {
    this.likeAndDislike = likeAndDislike;
    this.genle = genle;
  }

  //好き嫌いとジャンルを表示するメソッド
  callName(this: Foods) {
    console.log(
      `(好きor嫌い)${this.likeAndDislikes} : (ジャンル)${this.genle}`
    );
  }

 //食べ物リストに追加するメソッド
  addFoodList(food: string) {
    this.foodList.push(food);
  }

  //食べ物リストを表示するメソッド
  printFoodListInfo() {
    console.log(`リスト数:${this.foodList.length},${this.foodList}`);
  }
}

//好きな食べ物(果物)に関するインスタンスを作成
const favoriteFruits = new Foods("好きな食べ物", "果物");

//嫌いな食べ物(野菜)に関するインスタンスを作成
const dislikedVegetables = new Foods("嫌いな食べ物", "野菜");

//好きな果物リストにりんごを追加
favoriteFruits.addFoodList("りんご");

//好きな果物リストにメロンを追加
favoriteFruits.addFoodList("メロン");

//嫌いな野菜リストに追加
dislikedVegetables.addFoodList("きゅうり");

//favoriteFruitsインスタンスの好き嫌いとジャンルを表示。
favoriteFruits.callName();

//好きな果物リストを表示。
favoriteFruits.printFoodListInfo();//リスト数:2,りんご,メロン

//嫌いな野菜リストを表示。
dislikedVegetables.printFoodListInfo();//リスト数:1,きゅうり

今回はこのようなコードを準備しました。
このコード上で修飾子について少し記述します。

public

このclassにおいてgenleプロパティはpublicに指定されています。つまり外部からアクセスすることが可能になっています。簡単にgenleプロパティが書き換えられてしまう可能性が出てくるわけです。
どういう事かというと、

favoriteFruits.genle = "麺類";//好きな果物インスタンスのジャンルを麺類に書き換える。
favoriteFruits.callName();//(好きor嫌い)嫌いな食べ物 : (ジャンル)麺類 

このように好きな食べ物に関するインスタンスのつもりが簡単にジャンルが麺類に変更することができてしまいます。

private

このような不具合を防ぐためにprivateが有効な手段となります。

favoriteFruits.likeAndDislike = "嫌いな食べ物"//好きな果物インスタンスを嫌いな食べ物に書き換える

このように記述してもlikeAndDislikeプロパティはprivateに指定されている為、エラーとなります。

readonly

またlikeAndDislikeプロパティはreadonlyに指定されている為、constructor関数実行時に初期化された後は読み取る事しかできなくなります。

constructor関数実行時の初期化のショートカット

この書き方でも問題ないのですがプロパティで定義して、constructor実行時に再度定義していて少し冗長です。なのでこのように書き換えることが可能です。

class Foods {
  private foodList: string[] = [];
  constructor(
    private readonly likeAndDislike: "好きな食べ物" | "嫌いな食べ物",
    public genle: string
  ) {}
・
・
・
以下略

このように記述することでプロパティの記述をなくすことができます。constructorの初期化時に定義すればよくなるので大分スッキリしました。

最終的なコード

class Foods {
  private foodList: string[] = [];
  constructor(
    private readonly likeAndDislike: "好きな食べ物" | "嫌いな食べ物",
    public genle: string
  ) {}

  callName(this: Foods) {
    console.log(`(好きor嫌い)${this.likeAndDislike} : (ジャンル)${this.genle}`);
  }

  addFoodList(food: string) {
    this.foodList.push(food);
  }

  printFoodListInfo() {
    console.log(`リスト数:${this.foodList.length},${this.foodList}`);
  }
}

const favoriteFruits = new Foods("好きな食べ物", "果物");
const dislikedVegetables = new Foods("嫌いな食べ物", "野菜");

favoriteFruits.addFoodList("りんご");
favoriteFruits.addFoodList("メロン");
dislikedVegetables.addFoodList("きゅうり");

//書き換え可能
// favoriteFruits.genle = "麺類";

favoriteFruits.callName();
favoriteFruits.printFoodListInfo();
dislikedVegetables.printFoodListInfo();

Discussion