이전 글 - TypeScript: Basic Type
클래스는 JavaScript 생태계 속에서도 TypeScript에만 있는 개념이 아니다. CoffeeScript나 ES2015를 사용해봤다면 이미 클래스를 몇 번 쯤은 사용해보았을 것이다. 이 글에서는 ES2015의 클래스를 알고 있다는 전제하에 TypeScript의 클래스의 몇 가지 다른 부분들에 대해서만 설명한다.
프로퍼티 정의
TypeScript의 클래스에서는 선언한 값만 객체의 프로퍼티 값으로 활용할 수 있다. 예를 들면,
1 | class Rect { |
이 코드는 ES2015에서는 잘 돌아가는 코드이다. 또한 클래스의 프로퍼티를 정의하는 일반적인 방법이다. 하지만 이 코드는 TypeScript에서는 Property 'width' does not exist on type 'Rect'.
라는 에러를 뿜으며 돌아가지 않는다. 말 그대로 TypeScript에서는 Rect
클래스에 width
프로퍼티가 정의되지 않은 상태이기 때문이다. TypeScript에서 프로퍼티를 정의하기 위해서는 다음과 같이 써야한다.
1 | class Rect { |
클래스 내부에 위와 같이 타입과 함께 사용할 프로퍼티를 선언할 수 있다. 또한 생성자로 넘겨받는 인수도 타입 선언을 해주면 정상적으로 동작한다.
Static 프로퍼티
ES2015에서는 클래스에 static
키워드를 제공하고 있다. 하지만, ES2015의 static
은 메소드 전용으로, 프로퍼티에는 활용할 수 없는 키워드다. 다행히도 TypeScript에서는 static
키워드를 프로퍼티에도 활용할 수 있다.
1 | class Rect { |
접근 제한자(Access modifier)
객체지향적으로 JavaScript를 사용하게 되면 늘 남는 아쉬움이 하나 있다. 바로 은닉화다. JavaScript에서는 접근 제한자를 지원하지 않기 때문에 기본적으로 프로퍼티에 대해 접근을 막을 수는 없다. 때문에 private 프로퍼티의 식별자의 맨 앞에 언더스코어(_
)를 넣어줌으로써 이 변수가 private으로 사용된다는 컨벤션을 사용하곤 하지만, 역시 외부에서의 접근을 막을 수 없다는 점에서는 동일하다. 이 문제는 ES2015에서도 동일하다. 하지만 TypeScript는 접근 제한자를 제공하기 때문에 이 문제를 해결할 수 있다.
사용법은 간단하다. 프로퍼티 선언시에 접근 제한자로 사용될 수 있는 private
, public
, protected
같은 키워드를 같이 선언해주면 된다.
1 | class Rect { |
기본적으로 접근 제한자를 사용하지 않는다면 모든 프로퍼티와 메소드는 public
이다.
생성자에서의 활용
생성자에서도 접근 제한자를 사용할 수 있다. 생성자로 넘겨지는 인수에 접근 제한자를 사용하게 되면 해당 클래스에 그 인수의 식별자 이름과 같은 식별자의 프로퍼티가 정의되고 넘겨진 값으로 할당된다. 예를 들면, 위의 코드는 아래와 같이 다시 쓸 수 있다.
1 | class Rect { |
인자로 넘긴 width
, height
값이 묵시적으로 객체 인스턴스 프로퍼티에 할당된 것을 알 수 있다.
Readonly 제한자
TypeScript에는 이외에도 readonly
라는 특별한 제한자를 하나 제공한다. 이름에서 쉽게 유추할 수 있듯이 읽기만 가능한 프로퍼티를 선언할 때 사용된다. 쉽게 말해 프로퍼티를 위해 사용할 수 있는 const
인 것이다.
readonly
는 접근 제한자와 섞어서도 사용할 수 있다. 다음과 같은 문법으로 사용한다.
1 | class Rect { |
쉽게 예상할 수 있었겠지만, readonly
프로퍼티에 새 값을 할당하려고 하면 에러를 출력하게 된다.
추상 클래스(Abstract class)
추상 클래스는 추상 메소드(Abstract method) 를 가질 수 있는 클래스다. 추상 메소드란 구현부가 없는 메소드다. 추상 클래스를 상속하는 클래스에서는 반드시 추상 클래스의 추상 메소드를 구현해야 한다. 또한 추상 클래스로는 객체 인스턴스를 생성할 수 없다. 상속용으로만 기능한다.
인터페이스(Interface)를 알고 계신 분이라면 인터페이스와 뭐가 다른지 궁금할 것이다. 인터페이스는 모든 메소드가 추상 메소드이다. 추상 클래스는 추상 메소드만 포함할 수 있는 것이 아니라, 실제 구현이 있는 메소드도 포함할 수 있다. 인터페이스는 이외에도 많은 기능들과 개념을 포함하고 있으므로, 이에 대해서는 다음 글에서 다루려고 한다.
다음 글 - TypeScript: 인터페이스(Interface)