JavaScript
TypeScript
LIGincDay 4

ES5とTypeScriptでクラスの実装を比べてみる

More than 3 years have passed since last update.

これまでのJavaScriptではclass文がなく、代わりに関数を使用してclassを実装していきます。このあたりが、class文に慣れた方がJavaScriptに戸惑う原因にもなっていると思います。

classを実装してみる

ここでは以下の流れのPersonクラスを作ります。

  1. Personクラスを定義
  2. nameプロパティをセット
  3. say、walkメソッドを実装
  4. インスタンスを生成
  5. メソッドを実行

JavaScriptで実装してみる

今まで通りJavaScriptでPersonというクラスを実装してみたいと思います。

var Person = function(name){
    this.name = name || "dammy";
}

Person.prototype.say = function() {
    console.log("Hello, I'm " + this.name);
};

Person.prototype.walk = function() {
    console.log(this.name + " is walking");
};

var p = new Person("Yuta");

// Hello, I'm Yuta
p.say();

// Yuta is walking
p.walk();

TypeScriptで実装してみる

今度はTypeScriptでclassを実装してみたいと思います。

class Person {
    constructor(
        private name:string = "dammy"
    ) {}

    public say():void {
        console.log("Hello, I'm " + this.name);
    }

    public walk():void {
        console.log(this.name + " is walking");
    }
}

var p = new Person("Yuta");

// Hello, I'm Yuta
p.say();

// Yuta is walking
p.walk();

1行目:classを定義しています。
2行目:クラスからインスタンスを作成した際に、自動的に実行されるメソッドで、主に初期化などを行います。引数に初期値を設定することができます。
privateやpublicはアクセス修飾子と呼ばれています。privateはクラス内のアクセスのみ許可しています。publicはクラス外のアクセスを許可します。
一般的にはプロパティはprivate、メソッドをpublicにするケースが多いと思います。

classを継承してみる

今度はPersonクラスを継承してPhotographerクラスを実装したいと思います。

  1. Photographerクラスを定義
  2. PhotographerクラスがPersonクラスを継承
  3. name,cameraプロパティをセット
  4. sayメソッドをオーバーライド
  5. release,hasCameraメソッドを定義
  6. インスタンスを生成
  7. メソッドを実行

JavaScriptで実装してみる

上と同じく従来通りのJavaScriptで記述します。

Personクラス

var Person = function(name){
    this.name = name || "dammy";
}

Person.prototype.say = function() {
  console.log("Hello, I'm " + this.name);
};

Person.prototype.walk = function() {
  console.log(this.name + " is walking");
};

Photographerクラス

var Photographer = function(name,camera){
    this.name = name || "dammy";
    this.camera = camera || "";
}

// Personを継承
Photographer.prototype = Object.create(Person.prototype);

Photographer.prototype.say = function() {
  console.log("Hello, I'm " + this.name + "! My job is photographer");
};

Photographer.prototype.release = function() {
  console.log("take a picture");
};

Photographer.prototype.hasCamera = function() {
  console.log(this.camera? true : false);
};

var photographer = new Photographer("Yuta","Nikon S2");

// Hello, I'm Yuta! My job is photographer
photographer.say();

// take a picture
photographer.release();

// true
photographer.hasCamera();

// Yuta is walking
photographer.walk();

TypeScriptで実装してみる

Personクラス

class Person {
    constructor(
        //private -> protected
        protected name:string = "dammy"
    ) {}

    public say():void {
        console.log("Hello, I'm " + this.name);
    }

    public walk():void {
        console.log(this.name + " is walking");
    }
}

Personクラスを少し書き直しました。
constructorでのnameをprivateからprotectedに変更しています。
protectedにする事で継承先からアクセスする事ができます。

Photographerクラス

class Photographer extends Person {
    constructor(
        protected name:string = 'dammy',
        private camera:string = ''
    ){
        super();
    }

    public say():void {
        console.log("Hello, I'm " + this.name + "! My job is photographer");
    }

    public release():void {
        console.log("take a picture");
    }

    public hasCamera():void {
        console.log(this.camera? true : false);
    }
}

var photographer = new Photographer("Yuta","Nikon S2");

// Hello, I'm Yuta! My job is photographer
photographer.say();

// take a picture
photographer.release();

// true
photographer.hasCamera();

// Yuta is walking
photographer.walk();

継承の見通しが良くなりました。クラスは宣言時にPersonを継承していることがわかります。
constructor内でsuper()を呼ぶことで、PhotographerクラスもPersonクラスで定義されているメソッドを呼ぶことがで、行の最後でphotographer.work()を確認することができます。

まとめ

今回はクラスについてまとめました。TypeScriptも選択肢のひとつに上がるようになるといいなと思ってます!