TypeScript 클래스
TypeScript의 클래스에 대해 알아보겠습니다.
ES(ECMAScript)6에서 도입되었습니다. 클래스는 클래스 기반 언어에 익숙한 개발자가 보다 빠르게 학습할 수 있는 문법을 제시하지만 새로운 객체지향 모델을 제공하는 것은 아닙니다. 클래스도 프로토타입 기반 패턴의 함수를 보다 직관적인 문법으로 보기 쉽게 만든 것입니다. TypeScript에서 지원하는 클래스는 ES6와 유사하지만 몇 가지 다른 고유한 기능이 있습니다.
1. 클래스
ES6의 클래스에서는 클래스 내부에 프로퍼티를 선언할 수가 없어서 생성자 안에서 선언해야 하지만, TypeScript의 클래스는 클래스 내부에 프로퍼티 선언이 가능하고 사용할 프로퍼티를 먼저 선언해줘야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // TypeScript Class class Unit { // 클래스 프로퍼티 사전 선언 public name: string; constructor(name: string) { // 클래스 프로퍼티에 값을 할당 this.name = name; } public move() { console.log(`${this.name} is moving.`); } } const unit = new Unit('Marine'); unit.move(); | cs |
2. 클래스의 접근 제한자
TypeScript의 클래스에서는 클래스 기반의 객체 지향 언어가 지원하는 접근 제한자를 동일하게 지원합니다. TypeScript에서 접근 제한자를 생략할 경우에는 암묵적으로 public이 선언됩니다.
TypeScript의 접근 제한자 종류와 특징은 다음과 같습니다.
접근 제한자 |
클래스 |
자식 클래스 |
클래스 인스턴스 |
public |
O |
O |
O |
protected |
O |
O |
X |
private |
O |
X |
X |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // TypeScript Class class Unit { // 프로퍼티 선언 public name: string; protected move: string; private attack: string; constructor(name: string, move: string, attack: string) { // 클래스 내부에서는 public, protected, private 모두 참조 가능. this.name = name; this.move = move; this.attack = attack; } } class Marine extends Unit { constructor(name: string, move: string, attack: string) { super(name, move, attack); // 자식 클래스 내부에서 public 참조 가능. console.log(this.name); // 자식 클래스 내부에서 protected 참조 가능. console.log(this.move); // 자식 클래스 내부에서 private 참조 불가능. console.log(this.attack); // error } } const unit = new Unit('Marine', 'Left', 'Fire'); // 클래스 인스턴스를 이용하여 외부에서 public 참조 가능 console.log(unit.name); // 클래스 인스턴스를 이용하여 외부에서 protected 참조 불가능. console.log(unit.move); // error // 클래스 인스턴스를 이용하여 외부에서 private 참조 불가능. console.log(unit.attack); // error | cs |
2.1 클래스 생성자 파라미터의 접근 제한자
생성자의 파라미터에도 접근 제한자 사용이 가능합니다. 접근 제한자가 사용된 생성자 파라미터는 암묵적으로 클래스 프로퍼티로 선언되고 초기화됩니다.
생성자 파라미터에 private을 사용하면 클래스 내부에서만 참조 가능하고, public을 사용하면 클래스 외부에서도 참조가 가능합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // TypeScript Class class Unit { // 생성자 파라미터에 접근 제한자를 사용하면 클래스 프로퍼티로 선언 및 초기화. constructor( public name: string, private move: string ) {} } const unit = new Unit('Marine', 'Left'); // 생성자 파라미터에 public을 사용한 경우 외부에서 참조 가능 console.log(unit.name); // 생성자 파라미터에 private을 사용한 경우 외부에서 참조 불가능 console.log(unit.move); // error | cs |
생성자 파라미터에 접근 제한자를 생략한 경우 생성자 파라미터는 생성자 내부의 지역 변수로 사용되어 외부에서 참조가 불가능하게 됩니다.
1 2 3 4 5 6 7 8 9 10 | // TypeScript Class class Unit { // 생성자 파라미터에 접근 제한자를 생략하면 생성자의 지역변수로 사용됨 constructor(name: string) { console.log(name); } } const unit = new Unit('Marine'); console.log(unit.name); // error | cs |
3. readonly 키워드
TypeScript에서는 readonly 키워드를 지원합니다. 클래스의 프로퍼티에 사용하면 해당 프로퍼티는 선언시 생성자 내부에서만 값의 할당이 가능하게 되는데 그 외의 경우에는 값의 할당이 불가능하여 읽기만 가능한 상태가 됩니다. 이러한 특징을 이용하여 상수의 선언에 주로 사용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // TypeScript Class class Unit { private readonly MAX_ATTACK: number; private readonly MAX_DEFENCE: number; constructor() { this.MAX_ATTACK = 9; this.MAX_DEFENCE = 3; } public check() { // readonly 키워드로 선언된 프로퍼티는 값의 재할당이 불가능. this.MAX_ATTACK = 50; // error this.MAX_DEFENCE = 30; // error console.log(`MAX_ATTACK: ${this.MAX_ATTACK}`); console.log(`MAX_DEFENCE: ${this.DEFENCE}`); } } const unit = new Unit(); unit.check(); | cs |
4. static 키워드
TypeScript에서는 클래스 내부의 프로퍼티와 메서드에 static 키워드 사용이 가능합니다. static 키워드를 사용하면 정적 프로퍼티와 정적 메서드로 정의되고 클래스의 인스턴스 생성없이 호출이 가능합니다. 반면에 인스턴스 생성후에는 호출할 수 없다는 특징이 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // TypeScript Class class Unit { public name: string; constructor(name) { this.name = name; } static staticMethod() { // static 메서드에서 this는 클래스 인스턴스가 아닌 클래스 자신을 가리키기 때문에 // this를 사용하여 접근할 수 없음 this.name = 'Marine'; // error return new Unit('Marine').name; } public method() { return this.name; } } console.log(new Unit('Firebat').method()); // 정적 메소드는 클래스 이름으로만 호출 가능. console.log(Unit.staticMethod()); // 정적 메소드는 인스턴스로 호출이 불가능 console.log(new Unit('Ghost').staticMethod()); // error | cs |
5. 추상클래스
클래스 내부에 일반적으로 사용하는 프로퍼티와 메서드 이외에 하나 이상의 추상 메서드가 포함된 클래스를 추상 클래스라고 합니다. 메서드명 앞에 abstract 키워드를 붙여서 선언하며 상속을 통한 구현에 이용되어 인스턴스 생성이 불가능합니다. 추상 클래스를 상속한 클래스는 상속받은 추상 메서드를 반드시 구현해야하는 특징이 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // TypeScript Abstract Class abstract class Unit { // 추상 메소드 abstract attack(): void; // 일반 메소드 public move(direction: string): void { console.log('move to ' + direction); } } // TypeScript Class class Marine extends Unit { // 추상 클래스를 상속한 경우 추상 메소드를 반드시 구현해야 함. public attack() { console.log('Attack!'); } } // 추상 클래스는 인스턴스 생성이 불가능. new Unit(); // error const marine = new Marine(); marine.move(); marine.attack(); | cs |
이상으로 TypeScript의 클래스에 대해 알아봤습니다.
※ Reference
이웅모 지음, 『Angular Essentials』, 루비페이퍼(2018), p129 ~ p.136 4.5 클래스
poiemaweb.com, 클래스, https://poiemaweb.com/typescript-class