りゅうじの学習blog

学習したことをアウトプットしていきます。

4/14 TypeScript Class構文

オブジェクト思考プログラミング(OOP)とは

  • OOPとは現実世界のものに見立ててプログラムする方法
  • どのようにアプリケーションを作るかという方法の一つ
  • 人間にとってわかりやすくロジックを分割する方法の一つ

どうやって作るの?となった時に、現実世界のものに見立ててみよう!という考え方です。

Classとは

  • オブジェクトの設計図
  • Classから作られたオブジェクトはインスタンスと呼ぶ
  • 似たようなオブジェクトを複数作成するときに便利

Classの定義

person.ts

class Person {
  name: string;
  constructor(initName: string) {
    this.name = initName;
  }
}
const yano = new Person('yano');
console.log(yano);

実行結果

Person: {
  "name": "Yano"
}

TypeScript playgroundで出力しています。

メソッド定義

やのさんに挨拶をしてもらうためのgreetingメソッドを定義しました。

class Person {
  name: string;
  constructor(initName: string) {
    this.name = initName;
  }
  greeting() {
    console.log(`おはようございます、${this.name}でございます`)
  }
}
const yano = new Person('Yano');
console.log(yano);
yano.greeting();

出力結果

"おはようございます、Yanoでございます"
  • このclass構文は省略した書き方ができますが、あえて基本から整理するために、省略していない書き方からアウトプットしています。

Classを型として使う方法

クラス宣言で重要な特徴として

クラスオブジェクトという値を作るものであると同時に、インスタンスの型を宣言するものであることです。

const yano = new Person('Yano');

// こうとも書けるということ
const yano: Person = new Person('Yano');

このPerson型は、「string型のnameプロパティを持っていて、greetingメソッドを持つ」ということです。

であれば、new Personで作られたインスタンスでなくとも、この特徴を満たすものならば、Person型とすることができます。

const yunosuke: Person = {
  name: 'minegishi',
  greeting: () => console.log('おはす!')
}
  • Personのインスタンスと同じ特徴のyunosukeオブジェクトにはPersonの型を定義できている

※これはクラス宣言特有の挙動であり、クラス式では型は作られません。

クラス式の一例

const Person = class {
 neme: string = ''
 greeting() {}
}

// インスタンス化はできる
const yano = new Person();

// error 型としては使えない
const yunosuke: Person = new Person();

クラス宣言は、変数名と型名の両方の名前空間に、同時に名前を作成する構文であるということです。

private publicのアクセシビリティ修飾子

なぜ必要か

やのさんに挨拶に加えて、年齢も話してもらいました。

class Person {
  name: string;
  age: number;
  constructor(initName: string, initAge: number) {
    this.name = initName;
    this.age = initAge;
  }
  greeting(this: Person) {
    console.log(`おはようございます、${this.name}でございます。年齢は${this.age}です。`)
  }
  incrementAge() {
    this.age += 1;
  }
}
const yano: Person = new Person('Yano', 27);
yano.greeting();
  • ageプロパティを追加
  • greetingメソッド内のテンプレートリテラルで年齢に関しての文言を追加
  • 実行すると年齢に+1 をするincrementAgeメソッドを追加

実行結果

"おはようございます、Yanoでございます。年齢は27です。"

greetingメソッドより前に、incrementAgeメソッドを実行

class Person {
  name: string;
  age: number;
  constructor(initName: string, initAge: number) {
    this.name = initName;
    this.age = initAge;
  }
  greeting(this: Person) {
    console.log(`おはようございます、${this.name}でございます。年齢は${this.age}です。`)
  }
  incrementAge() {
    this.age += 1;
  }
}
const yano: Person = new Person('Yano', 27);
yano.incrementAge();
yano.greeting();

実行結果

"おはようございます、Yanoでございます。年齢は28です。"
  • 年齢に+1がされて、28歳になりました

ここで問題があります。

class Person {
  name: string;
  age: number;
  constructor(initName: string, initAge: number) {
    this.name = initName;
    this.age = initAge;
  }
  greeting(this: Person) {
    console.log(`おはようございます、${this.name}でございます。年齢は${this.age}です。`)
  }
  incrementAge() {
    this.age += 1;
  }
}
const yano: Person = new Person('Yano', 27);
yano.incrementAge();
yano.age = 70;
yano.greeting();
  • yano.age = 70; に注目してください

実行結果

"おはようございます、Yanoでございます。年齢は70です。"

やのさんが70歳のおじいちゃんになってしまいました。

まだ若く有望な彼の年齢を、こうも簡単に変更できてしまっては困ります。

class Person {
  name: string;
  private age: number;
  constructor(initName: string, initAge: number) {
    this.name = initName;
    this.age = initAge;
  }
  greeting(this: Person) {
    console.log(`おはようございます、${this.name}でございます。年齢は${this.age}です。`)
  }
  incrementAge() {
    this.age += 1;
  }
}
const yano: Person = new Person('Yano', 27);
yano.incrementAge();
yano.age = 70;  // ageがコンパイルエラー
yano.greeting();
  • ageプロパティにprivate修飾子をつけています
  • yano.ageのageでコンパイルエラーが発生して、70を代入できないようになりました
  • class外からはアクセス不可能。class内では使用できます
  • プロパティのみではなく、メソッドにも使用可能です
  • console.log(yano.age)のように読み取りも不可です

※何もつけないとpublicになります

初期化の処理の省略記法

省略前

class Person {
  name: string;
  age: number;
  constructor(initName: string, initAge: number) {
    this.name = initName;
    this.age = initAge;
  }

省略後

class Person {
  constructor(public name: string, private age: number) {}

省略記法は、どのように省略されているかを理解しておくと良いと思います。

次回

静的プロパティ・静的メソッドから

参考

プロを目指す人のためのTypeScript入門

Udemy 超TypeScript入門 完全パック