카테고리 없음

TypeScript 클래스

honey.kikiki 2021. 10. 16. 02:20
728x90

타입스크립트 클래스

자바스크립트는 애초에 프로토타입기반을 이용해 상속을 구현합니다. 

ES6 에 존재하는 class 키워드를 이용해 구현할 수 있습니다. 타입스크립트도 이와 동일하게 class 키워드를 이용합니다.

1. 클래스 키워드

ES6 를 다루어보셨다면 기존에 생각했던 것과 동일합니다. class 키워드 뒤에 클래스 이름을 적어줍니다.

class Button {
    constructor() {
      // ...
    }
}

2. 생성자

클래스 기반 언어들에서는 생성자를 통해 멤버들을 초기화시켜줬습니다. ES6 에서도 동일하게 this. 을 이용하였던것이 생각납니다.

타입스크립트도 동일한데 다만, 사전에 등록되지 않은 프로퍼티를 초기화하려하면 에러를 내뱉습니다.

class Button {
    constructor(name: string) {
        this.name = name; // Error!
        // TS2339: Property 'name' does not exist on type 'Button'.
    }
}

다음으로 만들어야합니다.

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

해당 클래스의 프로퍼티를 미리 작성해줘야 합니다.

3. 상속

ES6 문법에서 사용하던 extends 키워드를 동일하게 사용합니다.

class Input {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    inputName() {
        console.log(`input name is ${ this.name }`);
    }
}
class Button extends Input {
    constructor(name: string) {
        super(name);
    }
}
const button = new Button('click me');
button.inputName(); // input name is click me

현재 상속계층은 Button  Input 을 상속받고있습니다.
하위클래스에서 constructor 를 정의하고싶다면 반드시 상위클래스의 constructor 를 호출해야만합니다. super(name) 을 보면 매개변수도 동일하게 전달하는것을 확인할 수 있습니다. 그리고 마지막에 inputName() 을 호출하여 콘솔로그에 찍히는 것도 볼 수 있습니다.

4. 오버라이드

타입스크립트에서도 오버라이드를 구현할 수 있습니다.

오버라이드(Override)란?
상위 클래스에서 정의한 메서드를 자식클래스에서 재정의 하는 것.

class Input {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    inputName() {
        console.log(`input name is ${ this.name }`);
    }
}
class Button extends Input {
    constructor(name: string) {
        super(name);
    }
    inputName() {
        console.log(`button name is ${ this.name }`);
    }
}
const button = new Button('kikiki');
button.inputName(); // button name is kikiki

inputName() 메서드를 하위클래스인 Button 에서 오버라이드 하여 호출했습니다. 출력결과가 다른것을 확인할 수 있습니다.

 

5. 접근제어자

public : 디폴트값, 어디에서나 접근가능.

protected : 상속받은 하위클래스만 접근가능.

private : 선언한 클래스 내에서만 접근가능.

 

5- 1 public

별도로 프로퍼티나 메서드 앞에 추가해주지않아도 됩니다. 명시적으로 다음과 같이 수정할 수 있습니다.

class Input {
    public name: string;
    public constructor(name: string) {
        this.name = name;
    }
    public inputName() {
        console.log(`input name is ${ this.name }`);
    }
}
class Button extends Input {
    public constructor(name: string) {
        super(name);
    }
    public inputName() {
        console.log(`button name is ${ this.name }`);
    }
}

5- 2 protected

선언한 클래스를 포함해 상속받는 하위클래스에서만 접근 가능합니다.

class Input {
    protected name: string;
    constructor(name: string) {
        this.name = name;
    }
    protected inputName() {
        console.log(`input name is ${ this.name }`);
    }
}
const input = new Input('input');
// console.log(input.inputName()); Error!
// TS2445: Property 'inputName' is protected and only accessible within class 'Input' and its subclasses.

public  constructor() 를 통해 인스턴스를 생성했지만 protected 접근제어자가 붙은 inputName() 는 외부에서 호출불가능한것을 볼 수 있습니다.

constructor()  protected가 붙는다면 해당 클래스는 바로 인스턴스화 될 수 없습니다. 상속받은 하위클래스에서 super 를 이용해 호출할 수 있습니다.

class Input {
    protected name: string;
    protected constructor(name: string) {
        this.name = name;
    }
    protected inputName() {
        console.log(`input name is ${ this.name }`);
    }
}
class Button extends Input {
    constructor(name: string) {
        super(name);
    }
    inputName() {
        console.log(`button name is ${ this.name }`);
    }
}
const button: Input = new Button('button');

5-3 private

선언한 클래스 내에서만 접근이 가능합니다. 보통 private 키워드가 붙은 프로퍼티는 _(언더바) 를 붙이는것이 통상적이라고 합니다. 이후에 외부에서 접근을 할 시에는 get / set 을 이용합니다.

class Input {
    private _name: string;
    protected constructor(name: string) {
        this._name = name;
    }
    get name(): string {
        return this._name;
    }
    set name(name: string) {
        this._name = name;
    }
}
class Button extends Input {
    constructor(name: string) {
        super(name);
        // console.log(this._name);  Error!
        // TS2341: Property '_name' is private and only accessible within class 'Input'.
    }
}
const button = new Button('my Button');
// get 호출
console.log(`button name is ${ button.name }`); // button name is my Button
// set 호출
button.name = 'my Button2';
// get 호출
console.log(`button name is ${ button.name }`); // button name is my Button2