TypeScript1.8 入門② (関数・クラス)


# 概要

[前回](http://qiita.com/gcfuji/items/a37474a9ce00c0599c44)の続き。

# TypeScriptの機能

## TypeScriptの関数宣言

### 引数の型付け

TypeScriptでは、引数にも型を付ける事ができる。

```js:sample.ts
function add(a: number = 10, b?: number): number {
  return a + b;
}

console.log(add(5, 3));
```

引数a, bはそれぞれnumber型を指定し、関数自体の返り値にもnumber型を指定している。
引数に型違いの値などを代入した場合は、コンパイル時にエラーを吐き出してくれる為、より安全なプログラムを作成する事が可能である。

#### その他

* 返り値がない関数の場合は、返り値の型をvoidを与えればよい。
* 引数をオプションにしたい場合は、引数の後に?をつければよい。
	* オプションを使う場合は、関数の処理の中で存在チェックで処理を振り分ける。
* 引数に初期値を与える事も可能である。
	* 引数が入ってきた場合は、入ってきた値を使う。

ちなみに、アロー関数(関数式)を使うとこんなに短く書ける。

```js:sample.ts
let add = (a: number, b: number): number => a + b;
```

#### 関数のオーバーロード

#### シグネチャ

関数の「引数」と「返り値」の組み合わせの事。
オーバーロードとは、要は **シグネチャ** が違えば、別の関数としてジャッジしてくれる機能の事。

```js:sample.ts
let add = (a: any, b: any): any => {
  if (typeof a === `string` && typeof b === `string`) {
    return `${a} ${b}`;
  }
  return a + b;
};

console.log(add(2, 5));
console.log(add(`hello`, `world`));
```

同じ関数でも、any型を使い、シグネチャで処理を振り分ける事が可能である。

## クラス

オブジェクト志向を実現する為の機能である。
クラスには、変数とメソッドをまとめて管理する事ができる。
(ES6のクラスでは、変数はキープできない。。。)

```js:sample.ts

class User {
  public name: string;

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

  sayHi(): void {
    console.log(`hi! iam ${this.name}`);
  }
}

let jack = new User(`Jack`);

console.log(jack.name);
jack.sayHi();

```

### アクセス修飾子

Javaなどで開発している人にはおなじみのアクセス修飾子も利用可能である。
アクセス修飾子を利用する事で、より安全なコードで開発する事が可能になる。

|Name|Description|
|----|-----------|
|public|どこからでもアクセス可能なメンバ(default)|
|protected|自分と自分の子クラスからアクセス可能なメンバ|
|private|外部からアクセス不可なメンバ|

### Constructor

これもJavaなどで開発している人にはお馴染みのメソッドである。
クラスがインスタンス化された時に必ず呼ばれるメソッドで、引数を受けて、クラスの初期化処理を行う事ができる。

また、インスタンス化する際に変数を宣言して、Constructorで初期化する処理はよく行われる工程な為、ショートハンドが用意されています。
とはいっても簡単で、Constructorの引数にアクセス修飾子をつけるだけです。
ぐっとコードが短くなるので、ぜひ使いましょう。

```js:sample.ts
class User {
  constructor(public name: string) {
  }

  sayHi(): void {
    console.log(`hi! iam ${this.name}`);
  }
}

let jack = new User(`Jack`);

console.log(jack.name); // "Jack"
jack.sayHi(); // "hi! iam Jack"
```

### getter / setter

これまたJavaなどではお馴染みのgetter / setterです。
アクセス修飾子で紹介した[private]はクラス内のみで利用したいメンバに付与するアクセス修飾子です。
[private]を利用する事で、他のクラスやインスタンスから直接呼出せなく出来る為、不要に値を変えられたり、呼び出されたりする事がなく安全なプログラムを組む事が可能になります。

ただし、完全に外部から遮断するのではなく、一部呼び出したり、値を変更したりしたい場合もあるかと思います。
その時に使えるのが、getter / setter という特殊なメソッドです。

```js:sample.ts

class User {
  constructor(private _name: string) {
  }

  sayHi(): void {
    console.log(`hi! iam ${this._name}`);
  }
  
  // 取得したい場合の特殊メンバ
  get name() {
    return this._name;
  }

  // 値を代入したい場合の特殊メンバ
  set name(newValue: string) {
    this._name = newValue;
  }
}

let jack = new User(`Jack`);

jack.name = `Eve`;
console.log(jack.name); // "Eve"
jack.sayHi(); // "hi! iam Eve"
```

get/setはあくまでも、修飾子的な役割で、```get 関数名``の様な形で利用します。
上記のコードでいうならば、get修飾子が付与されたnameメソッドを呼び出すイメージです。

注意点が2点あります。

1. コンパイルする際には,```tsc sample.ts -t ES6```でコンパイルする。
	* 古いコンパイラではgetter/setter/は使えません。
2. privateメンバには、慣習として[_]をつける。
	* これは慣習ですが、可読性を上げる為にも必ず付ける様にしましょう。

### 継承

あるクラスのメンバをそのまま受け継いだクラスを作成する際には「継承」という機能を使います。
表現として、継承元のクラスを「親クラス」、継承先のクラスを「子クラス」と呼びます。

```js:sample.ts

class User {
  constructor(protected _name: string) {}
  public sayHi(): void {
    console.log(`hi! i am ${this._name}`);
  }
}

class AdminUser extends User {
  private _age: number;
  constructor(_name: string, _age: number) {
    super(_name);
    this._age = _age;
  }
  public sayHi(): void {
    console.log(`my age: ${this._age}`);
    console.log(`my name: ${this._name}`);
    super.sayHi();
  }
}

let bob = new AdminUser(`Steve`, 25);
bob.sayHi();

```

#### superキーワード
子クラスは親クラスのメンバを受け継ぎますが、子クラス内で親クラスのメソッドを利用したいこともあると思います。
その際に利用できるのが、[super]キーワードです。
superキーワードを使うと、子クラスから親クラスのcontsrucotrを呼び出したり、メソッドを呼び出したりが可能になる為、無駄なコードが少なくなり、また保守性も高まります。

#### オーバーライド
オーバーロードと言葉が似ていますが、全く異なった機能です。
オーバーライドは子クラスで、親クラスと同名のメソッドを定義した際に、子クラスのメソッドが優先される機能の事を言います。
オーバーライドしているメソッドの中から、親クラスのメソッドをsuperキーワードを介して呼び出す事も可能です。

> protected修飾子は、自クラス及び子クラスのみアクセス可能とするアクセス修飾子です。

### 静的メンバ
今まで紹介したクラス内のメンバはクラスをインスタンス化して初めて利用できるものでした。
「静的メンバ」はインスタンスに紐付くメンバではなく、クラス自身に紐付くメンバです。

```js:sample.ts
class User {
  constructor(protected _name: string) {
    User.count++;
  }

  sayHi() {
    console.log(`Hi! I am ${this._name}`);
  }
  
  static count: number = 0;
  
  static showDescription(): void {
    console.log(`this class is about users`);
  }
}

let jack = new User(`Jack`);
let eve = new User(`Eve`);

console.log(User.count);
User.showDescription();
```

#### staticキーワード
staticキーワードを使う事で、クラス内に静的メンバを宣言する事が可能です。
静的メンバを利用する際は「クラス名.メンバ」とします。
上のソースでは、Userクラスがインスタンス化される度に、User.count++が走り、クラスがインスタンス化された回数を出力します。

# 終わり

今回はTypeScriptの「関数」と「クラス」に関して解説しました。
次回は、「インタフェース」について解説したいと思います。
続きは次回。