타입스크립트는 ES2015에 도입된 class 키워드를 완벽하게 지원합니다. 타입스크립트는 자바스크립트 클래스 기능에 타입 지정 및 기타 문법을 추가로 제공합니다.
1. 클래스 기초
(1) 클래스 선언
다음은 가장 기본적인 형태의 빈 클래스입니다.
class Point {}
이제 몇 가지 요소를 추가해보겠습니다.
class Point {
x: number;
y: number;
}
const pt = new Point();
pt.x = 0;
pt.y = 0;
(2) readonly
필드에 readonly를 추가해주면 생성자 외부에서 값을 할당할 수 없게 됩니다.
class Greeter {
readonly name: string = "world";
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName;
}
}
err() {
this.name = "not ok";
// Cannot assign to 'name' because it is a read-only property.
}
}
const g = new Greeter();
g.name = "also not ok";
// Cannot assign to 'name' because it is a read-only property.
(3) Constructor
컨스트럭터 constructor는 함수와 무척 유사한 기능을 합니다. 파리미터 추가, 타입 지정, 기본값 추가, 오버라이드가 가능합니다.
class Point {
x: number;
y: number;
//Normal signature with defaults
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
(4) Super Calls
자바스크립트와 마찬가지로 베이스 클래스가 있다면 super();를 호출해야 이를 사용할 수 있습니다. 아래의 경우에는 이를 먼저 호출하지 않아 오류가 발생하는 경우입니다.
class Base {
k = 4;
}
class Derived extends Base {
constructor() {
// Prints a wrong value in ES5; throws exception in ES6
console.log(this.k);
//'super' must be called before accessing 'this' in the constructor of a derived class.
super();
}
}
(5) Methods
클래스 내에 함수를 메소드(method)라고 합니다.
class Point {
x = 10;
y = 10;
scale(n: number): void {
this.x *= n;
this.y *= n;
}
}
let result = new Point()
result.scale(3)
console.log(`x: ${result.x}`, `y: ${result.y}`) // "x: 30", "y: 30"
이 때 클래스 내에 변수에 접근하기 위해 this를 사용한다는 점을 잊지마시기 바랍니다. 아래와 같이 시도할 경우 클래스 내부의 x가 아닌 외부의 x에 접근하게 됩니다.
let x: number = 0;
class C {
x: string = "hello";
m() {
// This is trying to modify 'x' from line 1, not the class property
x = "world";
// Type 'string' is not assignable to type 'number'.
}
}
2. 클래스 상속
다른 객체 지향 언어와 마찬가지로 타입스크립트의 클래스 또한 다른 베이스 클래스로부터 상속받을 수 있습니다.
(1) implements
implements를 사용하여 클래스가 특정 interface를 만족하는지 확인할 수 있습니다. 클래스가 올바르게 구현되지 않았을 경우 오류가 발생합니다. implemetns는 클래스가 인터페이스 타입으로 처리될 수 있는 지를 확인할 뿐 클래스나 메소드의 타입을 변경하지는 않습니다.
interface Pingable {
ping(): void;
}
class Sonar implements Pingable {
ping() {
console.log("ping!");
}
}
class Ball implements Pingable {
// Class 'Ball' incorrectly implements interface 'Pingable'.
// Property 'ping' is missing in type 'Ball' but required in type 'Pingable'.
pong() {
console.log("pong!");
}
}
(2) Extends
extends를 사용하여 클래스를 확장할 수 있습니다. 파생 클래스는 베이스 클래스의 모든 속성 및 메소드를 갖게 되며 추가적인 구성도 가능합니다.
class Animal {
move() {
console.log("Moving along!");
}
}
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
console.log("woof!");
}
}
}
const d = new Dog();
// Base class method
d.move(); // "Moving along!"
// Derived class method
d.woof(3); // "woof!" "woof!" "woof!"
(3) Overriding Methods
파생 클래스에서 베이스 클래스의 메소드를 오버라이딩할 수도 있습니다. super 키워드를 통해 베이스 클래스 메소드에 접근할 수 있습니다.
class Base {
greet() {
console.log("Hello, world!");
}
}
class Derived extends Base {
greet(name?: string) {
if (name === undefined) {
super.greet();
} else {
console.log(`Hello, ${name.toUpperCase()}`)
}
}
}
const d = new Derived();
d.greet(); // "Hello, world!"
d.greet("reader"); // "Hello, READER"
파생 클래스를 만들며 name 뒤에 ?를 더해 name?로 작성했습니다. 이는 매개 변수를 선택적으로 사용한다는 의미입니다. 해당 변수가 사용되지 않는 경우 undefined가 반환됩니다. 이어지는 if문에서 이를 처리하고 있습니다.
(4) 실행 순서
다음과 같은 클래스가 있다고 해보겠습니다.
class Base {
name = "base";
constructor() {
console.log("My name is " + this.name);
}
}
class Derived extends Base {
name = "derived";
}
// Prints "base", not "derived"
const d = new Derived(); // "My name is base"
console.log(d.name) // "derived"
이 경우 코드는 다음의 순서를 따라 실행됩니다.
- 베이스 클래스가 초기화됩니다.
- 베이스 클래스의 컨스트럭터가 실행됩니다.
- 파생 클래스가 초기화됩니다.
- 파생 클래스의 컨스트럭터가 실행됩니다.
3. 멤버 접근 제한자
(1) public
클래스 멤버의 기본 값은 public입니다. 누구나 어디에서든 클래스에 접근할 수 있습니다.
class Greeter{
public greet() {
console.log("hi!");
}
}
const g = new Greeter();
g.greet(); // "hi!"
(2) protected
protected 멤버는 클래스가 선언된 서브 클래스에서만 접근할 수 있습니다.
class Greeter{
public greet() {
console.log("Hello, " + this.getName());
}
protected getName() {
return "hi";
}
}
class SpecialGreeter extends Greeter {
public howdy() {
// OK to access protected member here
console.log("Howdy, " + this.getName());
}
}
const g = new SpecialGreeter();
g.howdy(); // "Howdy, hi"
g.greet(); // "Hello, hi"
g.getName(); // Property 'getName' is protected and only accessible within class 'Greeter' and its subclasses.
(3) private
private는 서브 클래스 내에서도 접근이 불가능합니다.
class Base {
private x = 0;
}
const b = new Base();
// Can't access from outside the class
console.log(b.x);
// Property 'x' is private and only accessible within class 'Base'.
(업데이트 예정)
- Generic Classes
- this
- abstract
참고 자료
'개발 > Typescript' 카테고리의 다른 글
| 타입스크립트 (2) 기본 사용 방법 (0) | 2022.12.20 |
|---|---|
| 타입스크립트 (1) 타입스크립트란? (0) | 2022.12.20 |
