プログラミング言語

【TypeScript】TypeScriptにおけるオブジェクト指向構文

【TypeScript】TypeScriptにおけるオブジェクト指向構文

目次

  1. Class
  2. 継承とアクセス修飾子
  3. interface
  4. パラメータプロパティ
  5. 抽象クラス
  6. 最後に

今回は、TypeScriptでオブジェクト指向プログラミングをする時に使う構文をいくつか紹介したいと思います。

JavaScriptでは、もともとオブジェクト指向の概念がなかったですが、ES6からオブジェクト指向構文がいくつか使えるようになりました。

もちろんTypeScriptもJavaScriptをベースにしているプログラミング言語なので、オブジェクト指向構文が使えます。

前回までのTypeScriptの記事をまだ読んでいない場合はそちらを是非そちらを読んでから本記事をご覧ください。

【TypeScript】TypeScriptとは?概要やメリット、環境構築からHelloWorld表示
https://www.dailyupblog.com/languages/1680/

【TypeScript】基本構文と基本型、interfaceやType Aliasまでをご紹介
https://www.dailyupblog.com/languages/1717/

【TypeScript】Union TypesとGenericsの使い方をご紹介 〜型操作応用編〜
https://www.dailyupblog.com/languages/1741/

前回:【TypeScript】TypeSriptにおけるnull・undefinedチェックについて
https://www.dailyupblog.com/languages/1761/

それでは行きましょう。

Class

Class(クラス)とは、オブジェクトの雛形を表したものになります。

JavaScript及びTypeScriptでは、以下に紹介するclass構文を使うことで、クラスが定義できます。

例えば、下記のような例です。

class UserClass {

	public name: string;
	public age: number;

	constructor(name: string, age: number) {
		this.name = name;
		this.age = age;
	}

	public introduction(): string {
		return `私の名前は${this.name}です。年齢は${this.age}歳です。`;
	}
}

const user01 = new UserClass("太郎",26);

console.log(user01.introduction());
//私の名前は太郎です。年齢は26歳です。

上記のように今回は、UserClassクラスを作成してみました。

クラスでは、まずプロパティを宣言します。

今回は「name: string」と「age: number」というプロパティを宣言しています。

その後、コンストラクターメソッドを書いています。

このコンストラクターとは、インスタンスを作成した際に実行されるメソッドのことで、今回は事前に宣言したプロパティの初期値を設定しています。

その後、introductionメソッドという関数を作りました。

これはnameとageの値を使用して、自己紹介文を返すものです。

これでクラスの準備は完了です。

そうしたら、このクラスを使用するために、クラスのインスタンスを生成します。

クラスのインスタンス生成にはnewを用います。

作成したインスタンスを用いて、クラス内のプロパティやメソッドを扱うことができます。

継承とアクセス修飾子

クラスには、あるクラスのプロパティやメソッドを他のクラスに引き継ぐ継承といった機能があります。

引き継ぎ元のクラスをスーパークラス(親クラス)といい、引き継ぎ先のクラスをサブクラスといいます。

また、継承と合わせてアクセス修飾子というものも紹介します。

アクセス修飾子は、プロパティやメソッドのアクセス範囲を設定することができる機能です。

アクセス修飾子は下記の3種類存在します。

  • public クラス外からのアクセス可能
  • protected クラス内及びサブクラス内からのアクセス可能
  • private クラス内のみアクセス可能

例えば、下記のような例です。

class Item {

	public name: string;
	protected price: number
	private manufacturer: string;

	constructor(name: string, price: number, manufacturer: string) {
		this.name = name;
		this.price = price;
		this.manufacturer = manufacturer;
	}

	public itemDataReference(): string {
		return `商品名:${this.name}\n価格:${this.price}\n製造元:${this.manufacturer}`;
	}
}

class Food extends Item {
	public getPrice() {
		return this.price; //エラーではない
	}
}

let item01 = new Item("トイレットペーパー",200,"株式会社〇〇");
let item02 = new Food("おにぎり",100,"株式会社××");

console.log(item01.itemDataReference());
//商品名:トイレットペーパー
//価格:200
//製造元:株式会社〇〇

console.log(item02.getPrice());
//100

console.log(item01.price);
console.log(item01.manufacturer);
//エラー

上記の例は、商品情報を管理するクラスです。

Itemクラスを用意しました。

Itemクラスで宣言した3つのプロパティにそれぞれに種類の異なるアクセス修飾子をつけています。

そして、FoodクラスというItemクラスから派生したサブクラスも用意しました。

このクラスはサブクラスなので、スーパークラスであるItemクラスのプロパティやメソッドを引き継いでいるので、「price」金額のみを返すgetPriceメソッドが用意されています。

そして2つのインスタンスを生成し、item01はItemクラスのインスタンスであり、item02はFoodクラスのインスタンスになります。

item01よりitemDataReferenceメソッドを呼び出していますが、この関数はpublicであり、アクセス可能なのでエラーにはなりません。

item02より、getPriceメソッドを呼び出していますが、この関数に関してもpublicでアクセス可能です。

ただ、「item01.price」と「item01.manufacturer」はそれぞれprotectedとprivateですので、どちらもエラーになります。

interface

下記の記事で、型注釈のinterfaceを紹介しました。

【TypeScript】基本構文と基本型、interfaceやType Aliasまでをご紹介
https://www.dailyupblog.com/languages/1717/#chapter-5

今回は、予告通りに、オブジェクト指向構文でのinterfaceの使い方を紹介します。

オブジェクト指向におけるinterfaceは、クラスにおけるプロパティやメソッドのキーと型をあらかじめ宣言しておき、クラスでそのinterfaceをimplementsして使用します。

下記の例を見てみましょう。

interface User {
	name: string,
	age: number,
	introduction: () => string;
}

class UserClass implements User {
	name: string;
	age: number;
	constructor (name: string, age: number) {
		this.name = name;
		this.age = age;
	}
	introduction ():string {
		return `私の名前は${this.name}です。年齢は${this.age}です。`;;
	}
}

let user01 = new UserClass("太郎", 26);

console.log(user01.introduction());

あらかじめUserというinterfaceを宣言しており、string型のnameプロパティ、number型のageプロパティ、string型を返すintroduction関数を設定しておきます。

その後のUserClassクラスでは、前もって宣言しておいたinteface「User」をimplementsしていますので、内容はinterface「User」と同じものになっています。

パラメータプロパティ

クラスのプロパティの作成と初期化をコンストラクターメソッドの引数の中でまとめて行うことができます。

この場合、引数とプロパティ名は同名になります。

下記の例です。

class User {
	private name: string;
	private age: number;
	private address: string;

	constructor(name:string, age:number, address:string) {
		this.name = name;
		this.age = age;
		this.address = address;
	}
}

↓↓↓

class User {
	constructor(private name:string, private age:number, private address:string) {};
}

上のクラスの書き方を下のように省略的に書くことができます。

抽象クラス

前述のinterfaceと少し似ていますが、abstract修飾子をつけることで、プロパティや内容のないメソッド(抽象メソッド)を含めたクラスを作成できます。

このクラスは、それ単体でインスタンスを生成するものではなく、継承したサブクラスでインスタンスを生成して使用します。

このクラスを抽象クラスといいます。

説明だけだとわかりにくいと思うので、下記例を紹介します。

abstract class Item {
	constructor(protected name:string){}
	public abstract getItemName (): string;
}

class Food extends Item {
	getItemName(): string {
		return `食品 - 商品名:${this.name}`
	}
}

class Clothes extends Item {
	getItemName(): string {
		return `服 - 商品名:${this.name}`
	}
}

let item01 = new Food("おにぎり");
let item02 = new Clothes("Tシャツ");

console.log(item01.getItemName()); //食品 - 商品名:おにぎり
console.log(item02.getItemName()); //服 - 商品名:Tシャツ

上記例は、商品クラスをカテゴリーによって細分化したものの商品情報を管理するシステムの例です。

まず抽象クラスであるItemクラスを用意しています。

この抽象クラスでは、string型のnameプロパティと抽象メソッドであるgetItemName関数を用意しました。

サブクラスでFoodクラスとClothesクラスを作成しました。

これらのクラスはそれぞれ食品と服のカテゴリーのクラスであり、Itemクラスをextendsしています。

FoodクラスはgetItemName関数では「食品 – 商品名:${this.name}」という内容の値を返し、ClothesクラスのgetItemName関数では「服 – 商品名:${this.name}」という内容の値を返し、それぞれ異なるカテゴリー名の値になります。

このように、抽象クラスに対して、具体的な内容(今回の例では商品カテゴリー)に関するクラスのことを具象クラスといいます。

最後に

今回は、TypeScriptにおけるオブジェクト指向構文について、いくつか紹介いたしました。

今回紹介した、classやinterface、抽象クラスなどを使いこなすことで、TypeScriptでオブジェクト指向プログラミングができます。

実際の開発現場でもTypeScriptでのオブジェクト指向プログラミングは、取り入れられていると思うので、頑張って慣れていきたいと思います。

前回の記事:【TypeScript】TypeSriptにおけるnull・undefinedチェックについて
https://www.dailyupblog.com/languages/1761/

関連記事

関連記事