Classes

장유진·2022년 6월 28일
1

TypeScript

목록 보기
8/14

https://www.typescriptlang.org/docs/handbook/classes.html

Classes

클래스가 가질 수 있는 멤버는 property, method, constructor이다. 클래스 내부에서 이 멤버들은 "this."를 통해 접근할 수 있다. 클래스 객체는 new라는 키워드를 사용하여 생성한다.

class Greeter {
  greeting: string;

  constructor(message: string) {
    this.greeting = message;
  }

  greet() {
    return "Hello, " + this.greeting;
  }
}

let greeter = new Greeter("world");

Inheritance

클래스는 상속을 사용하여 기존에 존재하던 클래스(base class 또는 superclass)를 확장한 새로운 클래스(derived class 또는 subclass)를 생성할 수 있다. 상속할 때에는 extends 키워드를 사용한다. derived class는 base class의 멤버들을 사용할 수 있다.

base class에 constructor가 존재할 경우 derived class에서 super를 사용하여 base class의 constructor를 초기화 시켜줘야 하며 base class의 멤버에 접근할 때에도 super 키워드를 사용해야 한다.

class Animal {
  name: string;
  constructor(theName: string) {
    this.name = theName;
  }
  move(distanceInMeters: number = 0) {
    console.log(`${this.name} moved ${distanceInMeters}m.`);
  }
}

class Snake extends Animal {
  constructor(name: string) {
    super(name);
  }
  move(distanceInMeters = 5) {
    console.log("Slithering...");
    super.move(distanceInMeters);
  }
}

Public, private, and protected modifiers

TypeScript에서는 기본적으로 클래스의 멤버들이 public으로 선언된다.

public 멤버는 제한없이 어디에서나 접근할 수 있고, private 멤버는 해당 클래스 내에서만 접근이 가능하다. 그리고 protected 멤버는 해당 클래스와 해당 클래스의 하위 클래스들 내에서만 접근이 가능하다.

TypeScript는 structural type system을 사용하지만 private와 protected 타입에 한해서는 모양이 같아도 실제로 같은 것이 아니라면 다른 타입으로 취급한다.

Readonly modifier

클래스의 멤버들을 readonly로 선언하여 변경이 불가하게 만들 수 있다. readonly 멤버들은 반드시 선언되었을 때 혹은 constructor에서 초기화되어야 한다.

Parameter properties

parameter property란 클래스의 멤버 변수를 constructor의 parameter 부분에 선언하는 것이다. 변수를 생성하고 그 뒤에 constructor parameter를 통해 값을 초기화하는 일을 한 번에 할 수 있다. 아래 예제에서 dad의 name은 선언과 동시에 "Man with the 8 strong legs"라는 string으로 초기화되었다.

class Octopus {
  readonly numberOfLegs: number = 8;
  constructor(readonly name: string) {}
}

let dad = new Octopus("Man with the 8 strong legs");
dad.name;

Accessors

TypeScripts에서는 클래스에서 getter와 setter 기능을 제공한다. 이 기능을 사용하면 잘못된 클래스의 사용을 막을 수 있다. 클래스 외부에서는 getter와 setter의 이름으로 클래스 변수에 접근할 수 있고, 실제 변수의 이름과 getter/setter의 이름은 똑같이 설정하면 안 된다. 또한 get만 있고 set이 없는 변수의 경우 자동으로 readonly로 취급된다.

const fullNameMaxLength = 10;

class Employee {
  private _fullName: string = "";

  get fullName(): string {
    return this._fullName;
  }

  set fullName(newName: string) {
    if (newName && newName.length > fullNameMaxLength) {
      throw new Error("fullName has a max length of " + fullNameMaxLength);
    }

    this._fullName = newName;
  }
}

let employee = new Employee();
employee.fullName = "Bob Smith";

Static properties

static 멤버는 클래스 객체에서 존재하는 멤버가 아니라 클래스 자체에서 존재하는 멤버이다. static 키워드를 통해 생성할 수 있으며 "클래스 이름."을 멤버 이름 앞에 붙여서 접근할 수 있다.

class Grid {
  static origin = { x: 0, y: 0 };

  calculateDistanceFromOrigin(point: { x: number; y: number }) {
    let xDist = point.x - Grid.origin.x; // static 멤버 사용
    let yDist = point.y - Grid.origin.y; // static 멤버 사용
    return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
  }

  constructor(public scale: number) {}
}

Abstract Classes

abstract class는 base class의 용도로 만들어진 클래스이지만, interface와 다르게 멤버를 직접 구현하는 것이 가능하다. abstract 키워드는 클래스 뿐만 아니라 클래스 멤버에도 사용할 수 있으며, abstract 멤버들은 반드시 derived class에서 구현되어야 한다.

abstract class Department {
  constructor(public name: string) {}

  printName(): void {
    console.log("Department name: " + this.name);
  }

  abstract printMeeting(): void; // must be implemented in derived classes
}

class AccountingDepartment extends Department {
  constructor() {
    super("Accounting and Auditing"); // constructors in derived classes must call super()
  }

  printMeeting(): void {
    console.log("The Accounting Department meets each Monday at 10am.");
  }

  generateReports(): void {
    console.log("Generating accounting reports...");
  }
}

Using a Class as an Interface

클래스는 타입을 생성하기 때문에 interface를 사용하는 자리에 동일하게 클래스를 사용할 수 있다.

class Point {
  x: number;
  y: number;
}

interface Point3d extends Point {
  z: number;
}

let point3d: Point3d = { x: 1, y: 2, z: 3 };
profile
프론트엔드 개발자

0개의 댓글