【JavaScript TypeScript】クラスのおさらい
TypeScriptやNest.jsを学習していると頻繁にクラスが出てくるので、クラスについての基本をおさらい!
以下のコードはUser
クラスをインスタンス化し、name
とage
プロパティを持つオブジェクトを作成し、変数 user に割り当てるもの。
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let user = new User("sho", 31);
1. インスタンスの作成
new User(...)
でUser
クラスの新しいインスタンス(オブジェクト)が作成される。
この時点ではインスタンスは空のオブジェクト{ }
。
2. インスタンスの初期化
constructor(name, age)
でインスタンスの初期化が行われる。
ここではインスタンスにname
とage
プロパティを追加し、それぞれのプロパティに引数で渡された値を割り当てる。
constructor(name, age) {
this.name = name;
this.age = age;
}
3. thisの補足
this
は現在のインスタンスを指すキーワード。
コンストラクタの中でthis.name
、this.age
とすると、空だったインスタンスにname
とage
プロパティが追加される。
イメージ
{
name
age
}
this.name = name
の左辺はインスタンスのプロパティ、右辺は引数を指す。
ここではname
プロパティに引数name
('sho')を割り当てることをしている。
まとめ
インスタンスの初期化はコンストラクタで行われ、this
を使って現在のインスタンスにプロパティを追加する。
コンストラクタに引数で渡された値をプロパティに割り当てることで初期化を行う。
{ name: 'sho', age: 31 }
super()メソッドの使用について。
親クラスを継承したサブクラスの中で、親クラスのコンストラクタを呼び出して初期化するために使用するメソッド。
以下のコードはEmployee
クラスをインスタンス化し、name
、age
、employeeId
プロパティを持つオブジェクトを作成し、変数employee
に割り当てるもの。
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Employee extends User {
constructor(name, age, employeeId) {
super(name, age);
this.employeeId = employeeId;
}
}
let employee = new Employee("sho", 31, 12345);
1. インスタンスの作成
new Employee(...)
でUser
クラスを継承したEmployee
クラスの新しいインスタンスが作成される。
2. インスタンスの初期化
super(...)
で親クラスのコンストラクタを呼び出し実行。
Employee
インスタンスにname
とage
プロパティにそれぞれの値が設定される。
this.employeeid = employeeId
によってemployeeId
プロパティに引数の値が設定される。
これによりインスタンスの初期化が完了!
class Employee extends User {
constructor(name, age, employeeId) {
super(name, age);
this.employeeId = employeeId;
}
}
先ほどのコードをTypeScriptで書き直します。
コード内に以下を付きする必要あり。
クラスの型定義
class ClassName {...}
の内部でプロパティの型を定義する。
引数の型定義
constructor(...)
の内部で引数の型を定義する。
冗長なコードが完成!
しかし、TypeScriptではもっと短くコードを書くシンタックスが存在します!
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class Employee extends User {
employeeId: number;
constructor(name: string, age: number, employeeId: number) {
super(name, age);
this.employeeId = employeeId;
}
}
let employee = new Employee("sho", 31, 12345);
class User {
constructor(public name: string, public age: number) {}
}
class Employee extends User {
constructor(name: string, age: number, public employeeId: number) {
super(name, age);
}
}
let employee = new Employee("sho", 31, 12345);
ポイント
constructor
の引数にアクセス修飾子(public
, private
, protected
など)を付ける。そうすると、
- 自動で引数と同名のプロパティが作成される!
- 渡された引数で初期化まで行ってくれる!
- クラス宣言時の型宣言も省略可能!
constructor(public name: string, public age: number) {}
以下はNest.jsでルーティングの役割を行うコントローラのコードの一部。
コードの概要
MoviesService
のインスタンスをmoviesService
プロパティとしてクラスに注入(DI)している。
その後コンストラクタで初期化をすることで、MoviesController
インスタンスがMoviesService
の機能を利用可能になる。
constructor(private readonly moviesService: MoviesService) {}
private
:クラス内部からしか使えないようにするアクセス修飾子
readonly
:読み取り専用にする修飾子
constructor(...) {}
でMoviesController
クラスの新しいインスタンスを作成し、MoviesService型
のmoviesService
プロパティで初期化を行なっている。
@Controller('movies')
export class MoviesController {
constructor(private readonly moviesService: MoviesService) {}
@Get()
async findAll(): Promise<Movie[]> {
return await this.moviesService.findAll();
}
@Get()
メソッドの中のthis
は、
MoviesController
のインスタンスを示している。
this.moviesService.findAll();
とは、
MoviesController
の現在のインスタンスのmoviesService
プロパティを通じて、MoviesService
クラスで定義したfindAll()
メソッドを使用する、ということ。