TypeScript書き方まとめ~クラス編１~

#オブジェクト指向とは


- 　オブジェクト指向はオブジェクトリテラルとClassの２通り作る方法があります


#オブジェクトリテラル
下記のようにキーと値の組み合わせがある、オブジェクトの型を定義する記法です。

```typescript
const n =
{
 name: {
    Name1: 'Petter',
    Name2: 'Quil'
 },
 age: 38,
 gender: 'male'
}
```

#Classのインスタンス

- インスタンス

```new クラス名()```で作成することができます。
インスタンスとはPersonクラスを元にして、 new を呼び出して作ったPersonオブジェクトです。
つまり、インスタンスはクラスからできた`オブジェクト`ということです。

- constructor

インスタンスが作成された時に```constructor```が実行されます。
constructorはインスタンスが作成されたときに実行されるので、```new Person('Quill')```のQuillが```constructor(initName: string)```のinitNameに入ります。
initNameを持つ`this.name`ですが、thisをつけることでPersonクラスのnameプロパティにアクセスでき、nameにinitNameの値が入ります。
`console.log(quill);`で最終的に`'Quill'`と表示されます。

```typescript
class Person {
    name: string;//プロパティ（値）
    constructor(initName: string){//最初の処理
      this.name = initName;
    }
  }
  const quill = new Person('Quill');//インスタンス作成(Personオブジェクト)
  console.log(quill);
```

#classのメソッド

メソッドはクラス内に書くことができます。
`const quill = new Person('Quill');
 `でconstructor経由でnameには'Quill'が入っており、`quill.greeting();`でgreetingメソッドが呼び出されます。greetingメソッド内のthis.nameはクラス内のnameを示すので、`quill.greeting();`では``Hello My name is Quill`と表示されます。

```typescript
class Person {
    name: string;

    constructor(initName: string){
      this.name = initName;
    }
  greeting() {
         
         console.log(`Hello My name is ${this.name}`);
     }
  }
  const quill = new Person('Quill');
  quill.greeting();
```


では次は新しく追加したanotherQuillオブジェクトでのthisの挙動を見てみましょう。
`quill.greeting();`では`Hello My name is Quill`を示しますが、新規に作成したオブジェクトで`anotherQuill.anotherGreeting();`を実行すると`Hello My name is undefined`になってしまいます。

クラスを用いずにオブジェクトを作った場合、greetingメソッドのthisはanotherQuillを示すので、anotherQuill内でnameを指定しないとundefinedとなってしまいます。

```typescript
class Person {
    name: string;
    constructor(initName: string){
      this.name = initName;
    }
  greeting() {
         
         console.log(`Hello My name is ${this.name}`);
     }
  }

  const quill = new Person('Quill');
  quill.greeting();

  //クラスを用いずにオブジェクトを作った場合、greetingメソッドのthisはanotherQuillを示すので、anotherQuill内でnameを指定しないとundefinedになる
  const anotherQuill = {
     anotherGreeting: quill.greeting    
 }
anotherQuill.anotherGreeting();
```
anotherQuill内でnameを定義するとgreetingメソッドのthisはanotherQuillオブジェクト内のnameを参照できるので、`Hello My name is anotherQuill`となります。

thisは定義されたときでなく、呼び出されたときに決まります。
なので、`quill.greeting();`の時点ではgreetingのthisはPerson内でのnameを示し、`anotherQuill`ではanotherQuill内でのnameを示します。

```typescript
const anotherQuill = {
　　　name: 'anotherQuill',
     anotherGreeting: quill.greeting    
 }
anotherQuill.anotherGreeting();
```

因みにですが、下記のようにanotherQuillにnameを指定しなくてもエラ-は起きません。何故なら、typescriptはquill.greetingのgreetingメソッドのthisがどこで使われてるかまでは見ないからです。

```typescript
 greeting() {
         console.log(`Hello My name is ${this.name}`);
     }

const anotherQuill = {
     anotherGreeting: quill.greeting    
 }
anotherQuill.anotherGreeting();
```

しかし、下記のようにgreetingメソッドにthisを追記するとanotherQuill.anotherGreeting();のanotherQuillがエラーになります。これはgreetingメソッドにthisを追記することでanotherGreeting: quill.greetingのthisがどれを指してるのかtypescriptが理解できるからです。
エラーの原因はanotherQuillにnameが無いことなのでnameを指定する必要があります。

```typescript
//引数にthisをつけることでメソッドが呼び出された時にthisの内容を伝えれる
 greeting(this: {name: string}) {
         console.log(`Hello My name is ${this.name}`);
     }

const anotherQuill = {
     anotherGreeting: quill.greeting    
 }
anotherQuill.anotherGreeting();
```
anotherQuillに`name: 'anotherQuill'`を指定することでエラーは解消されます。

```typescript
const anotherQuill = {
　　　name: 'anotherQuill',
     anotherGreeting: quill.greeting    
 }
anotherQuill.anotherGreeting();
```

- アロー関数

アロー関数にすることで、通常の関数のthisは呼び出し時に決まるが、アロー関数だと定義時にthisが決まるので今回だと'Quill'が出続ける

```typescript

greeting() => {   
   console.log(`Hello My name is ${this.name}`);
  }
```

#クラスを型として使う

`this: Person`とすることでクラスを型として使えます。`let person2: Person;`とすることでprson2はnemeとgreetingメソッドを持つオブジェクトになります。

```typescript
class Person {
    name: string;
    constructor(initName: string){
      this.name = initName;
    }
  greeting(this: Person) {

         console.log(`Hello My name is ${this.name}`);
     }
  }
let person2: Person;
```

anotherQuillは下記のようになります。quill.greetingのgreetingのthisはnameとgreetingメソッドを示しているので`greeting() {}`を追記する必要があります。
Personを再現しないと使えないようにすることでエラーを防ぐことができます。

```typescript
const anotherQuill = {
　　　name: 'anotherQuill',
     greeting() {},
     anotherGreeting: quill.greeting    
 }
anotherQuill.anotherGreeting();
```