타입스크립트는 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 |