0
1

More than 1 year has passed since last update.

基礎の「き」。Typescriptで学ぶ「クラス」

Posted at

はじめに

最近、プログラミング初学者の天敵(?)である「クラス」をようやく退治する気になりました。
という訳で、本記事ではTypescriptにおける「クラス」について基礎から探っていきます。

※執筆者である私は、プログラミング初学者です。そのため扱うレベルが低く、内容に誤りが含まれている可能性もありますが、ご容赦下さい。

クラスとは?

JavascriptやTypescriptにおいて、オブジェクトを生成する方法は2つあります。
①オブジェクトリテラル
②クラス

①のオブジェクトリテラルは、直接オブジェクトを生成する方法です。

//こんな感じ
const point = {
  x: 1,
  y: 2
}

一方、クラスとはオブジェクトの設計図のようなものです。
設計図を用意しておき、必要な場面でオブジェクトを生成します。
同じようなオブジェクトが複数必要な場合は、クラスを用いると便利です。

クラスの定義

一例ですが、クラスは下記のように定義されます。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}

var p1 = new Point(0, 10);
var p2 = new Point(10, 20);

classというキーワードを使って、クラスが定義されています。
何か色々と見慣れないものが出てきましたが、まずこの部分に着目します。

var p1 = new Point(0, 10);
var p2 = new Point(10, 20);

定義されたクラスを、上記の記述によって、オブジェクトを作成しています。
クラスから作成されたオブジェクトは、「インスタンス」と呼ばれます。

仮にクラスを使用しないとなると、p1やp2といったオブジェクト毎に記述が必要になってしまいます。
クラスの便利さが何となく分かってきました。

console.log()でオブジェクトを確認しておきます。

console.log(p1)
console.log(p2)
console.log(Point)

//結果 下記のようなオブジェクトが出来上がる。
{
  "x": 0,
  "y": 10
} 
{
  "x": 10,
  "y": 20
} 

コンストラクタ

次は、下記部分を理解していきます。

constructor(x: number, y: number) {
   this.x = x;
   this.y = y;
}

これは「コンストラクタ」と呼ばれるメソッドです。コンストラクタは、newでインスタンス(オブジェクト)を作成する際に、最初に呼び出される特別なメソッドです。
コンストラクタは、オブジェクトの作成に必要な「引数」を渡す役割を担います。
クラスは設計図です。そこに、データ(引数)を渡すことで、個別のインスタンス(オブジェクト)が作成されます。
データ(引数)は、コンストラクタというメソッドを用いて、クラスに渡されます。

var p1 = new Point(0, 10); //0,10 がコンストラクタメソッドの引数に渡される。
var p2 = new Point(10, 20); //10,20がコンストラクタメソッドの引数に渡される。

コンストラクトを用いないと?

コンストラクタを用いない場合、どういう記述になるか気になりました。
こんな感じでしょうか?

class Point {
    x: number;
    y: number;
}

var p1 = new Point();
p1.x = 0;
p1.Y = 10
var p2 = new Point();
p2.x = 10;
p2.Y = 20;

コンストラクタを用いたほうが、簡単にインスタンスが作成できそうです。

クラスにメソッドを追加する

クラスにはメソッドを追加することが出来ます。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    //functionは省略して記述される。
    showNumber() {
        console.log(`x:${this.x}, y:${this.y}`);
    }
    //function showNumber() {
        // return new Point(this.x + point.x, this.y + point.y);
    // }  
}

var p1 = new Point(0, 10);
//メソッドを呼び出す。
p1.showNumber()

クラス内の値を参照する時は、thisを用います。thisの挙動については、非常に面白いので後述します。

クラス内のメソッドの活用

クラス内のメソッドは、例えば下記のように活用することができます。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    add(point: Point) {
        return new Point(this.x + point.x, this.y + point.y);
    }
}

var p1 = new Point(0, 10);
var p2 = new Point(10, 20);
var p3 = p1.add(p2); // {x:10,y:30}

難しいですね。
ちなみにこれらのコードは、公式ドキュメントから拝借しています。

流れとしては、こんな感じでしょうか。
①p1,p2オブジェクトの作成
②p1オブジェクトの、addメソッドを呼び出す。その際、引数としてp2オブジェクトが渡される。(p1.add(p2)の部分)
③addメソッドは、新しいインスタンス(オブジェクト)を作成する(返す)。

そして、p3をconsole.log()で確認すると、{x:10,y:30}が出力される。
p1{x:0,y:10}にp2{x:10,y:20}が加算され、{x:10,y:30}になっています。

クラスを定義すると、自動で型が生成される。

この部分に着目してみて下さい。

//引数に型Pointが指定されている。
add(point: Point) {
      //省略
 }

引数にPoint型が指定されています。
Point型がいつ定義されているかというと、クラスを定義したタイミングです。
クラスを定義したタイミングで、そのクラスの型が自動で作成されます。
この場合Point型は、x,yプロパティ、addメソッドを持つオブジェクトです。

add(point: Point)において、addメソッドの引数には、Point型しか渡せないという指定になっています。

thisの挙動

ここからは少々マニアック?な話になります。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    showNumber() {
        console.log(`x:${this.x}, y:${this.y}`);
    }
}

var p1 = new Point(0, 10);
p1.showNumber()

//結果
"x:0, y:10"

上記のようなコードを、以下のように書き換えてみます。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    showNumber() {
        console.log(`x:${this.x}, y:${this.y}`);
    }
}

var p1 = new Point(0, 10);
const anotherP1 = {
  anotherShowNumber: p1.showNumber
}
anotherP1.anotherShowNumber()

//結果
 "x:undefined, y:undefined" 

undefinedになってしまいますね。
オブジェクトの中でthisを使用した場合、thisはそのオブジェクトを示します。
つまりこの場合のthisは、anotherP1を参照しているのです。

例えばこのように記述してみます。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
    showNumber() {
        console.log(`x:${this.x}, y:${this.y}`);
    }
}

var p1 = new Point(0, 10);
const anotherP1 = {
  x: 100, //追加
  y: 200, //追加
  anotherShowNumber: p1.showNumber
}
anotherP1.anotherShowNumber()

//結果
 "x:100, y:200" 

thisの使用についてはまだまだ追求できそうですが、とりあえずここまでにしておきます。
興味のある方は、class内のメソッドをアロー関数で記述したらどうなるか、試してみると面白いです。

最後に

長くなったので、続きは別の記事にしておきます。
次回以降は、クラスの継承やメソッドのオーバーライド、アクセス修飾詞、setterとgetterについて触れていきます。

参考

TypeScript Deep Drive 日本語版
超TypeScript入門 完全パック(2021)
TypeScriptハンズオン

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1