개발일지

클래스 - Class in TypeScript 본문

frontEnd/Typescript

클래스 - Class in TypeScript

푸린푸린김푸린 2023. 12. 18. 15:13

 

클래스 Class

타입스크립트에서는 클래스의 필드를 선언할 때 타입 주석으로 타입을 함께 정의해주어야 한다. 그렇지 않으면 함수 매개변수와 동일하게 암시적 any 타입으로 추론된다 => stric : true에서 오류 발생 !

+ 생성자에서 각 필드의 값을 초기화 하지 않을 경우 초기값도 함께 명시 필요

class Student {
  // 필드
  name: string = "";
  age: number = 0;
  position: string = "";

  // 메서드
  work() {
    console.log("공부함");
  }
}

 

만약 아래와 같이 생성자 함수에서 필드의 값들을 잘 초기화해뒀다면 필드 선언 시의 초기값은 생략 가능하다

class Student {
  // 필드
  name: string = "";
  age: number = 0;
  position: string = "";
  // position?: string = ""; //선택적 프로퍼티 사용가능

  // 생성자
  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  work() {
    console.log("공부함");
  }
}

 

 

클래스는 타입이다

 

흠칫하게되는 그날의 기억....

 

 

 

 

 

 

TS의 클래스는 타입으로도 사용할 수 있다. 클래스를 타입으로 사용하면 해당 클래스가 생성하는 객체의 타입과 동일한 타입이 된다

class Student {
  (...)
}

const studentA: Student = {
  name: "",
  age: 0,
  position: "",
  study() {},
};

변수 studentA의 타입을 Student클래스로 정의했다.

따라서 이 변수는 name, age, position 프로퍼티와 study메서드를 갖는 객체 타입으로 정의된다.

 

 

상속

TS에서 클래스의 상속을 이용할 때 파생 클래스(확장하는 클래스)에서 생성자를 정의 했다면 반드시 super 메서드를 호출해 슈퍼 클래스(확장되는 클래스)의 생성자를 호출해야 하며, 호출 위치는 생성자의 최상단 이어야만 한다.

class ExecutiveOfficer extends Student {
  schoolNumber: number;

  constructor(
    name: string,
    age: number,
    position: string,
    schoolNumber: number
  ) {
    super(name, age, position);
    this.schoolNumber = schoolNumber;
  }
}

 

 

 

접근 제어자 (Access Modifier)

접근 제어자는 타입스크립트에서만 제공되는 기능으로 클래스의 특정 필드나 메서드를 접근할 수 있는 범위를 설정할 수 있다.

  • public : 모든 범위에서 접근 가능
  • protected : 클래스 내부에서만 접근 가능
  • private :클래스 내부 또는 파생 클래스 내부에서만 접근 가능

 

public

어디서든지 이 프로퍼티에 접근할 수 있으며 생략 가능한 default값이다

class Student {
  // 필드
  name: string;      // 자동으로 public
  age: number;       // 자동으로 public
  public position: string;  // 물론 이렇게 직접 명시할 수도 있음

  // 생성자
  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  study() {
    console.log("공부하느라 허리가 뿌러지겠음");
  }
}

const student = new Student("lee", 17, "student");

student.name = "홍길동";
student.age = 30;
student.position = "디자이너";

 

 

 

private

특정 필드나 메서드의 접근 제어자를 private으로 설정하면 클래스 내부에서만 이 필드에 접근할 수 있게 된다.

( 해당 클래스의 인스턴스에서만 접근 가능 )

class Student {
  // 필드
  private name: string;      // private 접근 제어자 설정
  age: number;       // 자동으로 public
  public position: string;  

  // 생성자
  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  study() {
    console.log(`${this.name}은 공부하느라 졸려 죽겠음`);	// 여기서는 접근 가능
  }
}

const student = new Student("lee", 17, "student");

student.name = "홍길동";	// ❌ 여기서는 오류
student.age = 30;
student.position = "디자이너";

 

 

 

protected

private과 public의 중간으로 클래스 외부에서는 접근이 안되지만 클래스 내부와 파생 클래스에서 접근이 가능하도록 설정하는 접근 제어자

( 해당 클래스 혹은 서브클래스의 인스턴스에서만 접근 가능 )

class Student {
  // 필드
  private name: string;      // private 접근 제어자 설정
  protected age: number;       // protected 접근 제어자 설정
  public position: string;  

  // 생성자
...

  // 메서드
  study() {
    console.log(`${this.name}은 공부하느라 졸려 죽겠음`);	// 여기서는 접근 가능
  }
}

class studentBodyPresident extends Student {
 // 메서드
  func() {
    this.name; // ❌ 오류 
    this.age; // ✅ 가능
  }
}

const student = new Student("lee", 17, "student");

student.name = "홍길동";	// ❌ 오류
student.age = 30;	// ❌ 오류
student.position = "디자이너";

 

 

 

필드 생략하기

접근 제어자는 생성자의 매개변수에도 설정이 가능하다

class Student {
  // 필드
  private name: string;      // ❌ 싹
  protected age: number;      // ❌ 다
  public position: string;    // ❌ 오류

  // 생성자
  constructor(
    private name: string,
    protected age: number,
    public position: string	// 이렇게 생성자의 매개변수에도 접근제어자 설정 가능
  ) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  study() {
    console.log(`${this.name}은 공부하느라 싱싱미역`);	
  }
}

 

하지만 생성자에 접근 제어자를 설정하면 동일한 이름의 필드를 생성하지 못한다.

=> 생성자 매개변수에 접근 제어자가 설정되면 자동으로 필드도 함께 선언되기 때문

해결방법

그래서 위의 오류 코드는 필드 선언을 싹 지워주면 된다

class Student {
 // 생성자
  constructor(
    private name: string,
    protected age: number,
    public position: string	// 이렇게 생성자의 매개변수에도 접근제어자 설정 가능
  ) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  // 메서드
  study() {
    console.log(`${this.name}은 공부하느라 싱싱미역`);	
  }
}

 

그리고 또 추가로 이렇게 접근 제어자가 설정된 매개변수들은 this.필드 = 매개변수 가 자동으로 수행된다

그래서 위의 name,age,postion이 모두 this객체의 프로퍼티 값으로 자동 설정되기 때문에 또 아래와 같이 내부 코드도 싹 제거해도 된다

class Student {
 // 생성자
  constructor(
    private name: string,
    protected age: number,
    public position: string	// 이렇게 생성자의 매개변수에도 접근제어자 설정 가능
  ) {} // 싹 제거 !

  // 메서드
  study() {
    console.log(`${this.name}은 공부하느라 반갈죽`);	
  }
}

 

그래서 TS에서 클래스를 사용할 때에는 생성자 매개변수에 접근 제어자를 설정하여 필드 선언과 생성자 내부 코드를 생략한다면 빠르게 코드를 작성할 수 있다 !

 

 

인터페이스와 클래스

TS의 인터페이스는 클래스의 설계도 역할을 할 수 있다 !
인터페이스를 이용해 클래스에 어떤 필드들이 존재하고, 어떤 메서드가 존재하는지 정의할 수 있다

// 요로코롬
interface CharacterInterface {
  name: string;
  moveSpeed: number;
  move(): void;
}

class Character implements CharacterInterface {
  constructor(
    public name: string,
    public moveSpeed: number,
    private extra: string
  ) {}

  move(): void {
    console.log(`${this.moveSpeed} 속도로 이동!`);
  }
}

 

인터페이스 CharacterInterface는 name, moveSpeed 프로퍼티와 move 메서드를 갖는 객체 타입을 정의한다.

그런데 이 인터페이스를 클래스에서 implements 키워드와 함께 사용하면 이제부터 이 클래스가 생성하는 객체는 모두 이 인터페이스 타입을 만족하도록 클래스를 구현해야 한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

reference.

한 입 크기로 잘라먹는 타입스크립트(TypeScript).섹션4-함수와 타입.https://www.inflearn.com/course/한입-크기-타입스크립트

한 입 크기로 잘라먹는 타입스크립트 핸드북.https://ts.winterlood.com/타입스크립트의 클래스

타입스크립트 접근제한자(public, protected, private)(21.11)https://www.howdy-mj.me/typescript/access-modifiers

 

 

 

 

 

Comments