포시코딩

[TypeScript][노마드코더] #4 CLASSES AND INTERFACES(1) 본문

JavaScript

[TypeScript][노마드코더] #4 CLASSES AND INTERFACES(1)

포시 2023. 1. 20. 20:13
728x90

Class 클래스

TypeScript에서 Class를 만들 때 기존 JavaScript에서 하던 행동들을 줄일 수 있다.

 

예시

TypeScript

Class Player {
  constructor (
    private firstName: string, 
    private lastName: string
  )
}

변환된 JavaScript

class Player {
  constructor (firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}

 

하지만 private 선언을 한게 사라졌는데

위에서 private 키워드는 오로지 TypeScript가 보호해주기 위해서만 사용하는 것이고

JavaScript에서는 사용되지 않는다.

 

TypeScript

Class Player {
  constructor (
    private firstName: string, 
    private lastName: string, 
    public nickname: string
  )
}

const nico = new Player("nico", "las", "니꼬");

nico.firstName; // Error

실제로 위와 같이 코드를 작성했을 경우 firstName이 private이라 에러가 발생하는 것을 볼 수 있다.

* 하지만 JavaScript에서는 에러가 나타나지 않는 것을 볼 수 있는데 

일반적인 JavaScript에 불과하여 private이나 public 같은 보호를 받지 못한다. (애초에 트랜스파일이 안되긴 함)

 

Abstract Class 추상 클래스

추상 클래스란?

다른 클래스가 상속받을 수 있는 클래스를 의미한다.

하지만 이 클래스는 직접 새로운 인스턴스를 만들 수 없다.

 

TypeScript

abstract class User {
  constructor (
    private firstName: string, 
    private lastName: string, 
    public nickname: string
  )
}

class Player extends User {
  
}

const nico = new User("nico", "las", "니꼬");  // Error
const nico = new Player("nico", "las", "니꼬");

 

추상 클래스 안의 메소드와 추상 메소드 (Abstract Method)

정상 작동 하는 경우

abstract class User {
  constructor (
    private firstName: string, 
    private lastName: string, 
    public nickname: string
  ){}
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {
  
}

const nico = new Player("nico", "las", "니꼬");
nico.getFullName();

private으로 인한 에러 상황

abstract class User {
  constructor (
    private firstName: string, 
    private lastName: string, 
    public nickname: string
  ){}
  private getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {
  
}

const nico = new Player("nico", "las", "니꼬");
nico.getFullName();  // Error

 

추상 메소드란?

추상 메소드는 추상 클래스를 상속받는 모든 것들이 구현 해야하는 메소드를 의미

구현은 어떻게 되도 상관 없지만 구현이 되야 한다.

 

추상 메소드 만드는 법

메소드를 클래스 안에서 구현하지 않으면 된다.

 

추상 클래스 안에서는 추상 메소드를 만들 수 있음.

하지만, 메소드를 구현해서는 안되고 대신 메소드의 call signature만 적어야 한다.

 

abstract class User {
  constructor (
    private firstName: string, 
    private lastName: string, 
    private nickname: string
  ){}
  abstract getNickName(): void  // 메소드의 call signature만 가지고 있는 모습. 즉, 추상 메소드
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {  // Error! : Player가 getNickName을 구현해야 한다라고 알려주는중
}

Player가 getNickName()을 구현하지 않아 에러가 발생한 모습.

아래처럼 진행한다.

 

abstract class User {
  constructor (
    private firstName: string, 
    private lastName: string, 
    private nickname: string
  ){}
  abstract getNickName(): void
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {
  getNickName() {
    // console.log(this.nickname)  // nickname을 private property로 만들었기 때문에 사용불가
  }
}

const nico = new Player("nico", "las", "니꼬");
nico.getFullName();

만약 property를 private으로 만든다면,

인스턴스 밖에서 해당 property에 접근할 수 없다.

다른 자식 클래스에서 추상 클래스를 상속하였어도 해당 property에 접근할 수 없다.

(추상 클래스 즉, 위에서 User 클래스의 인스턴스나 메소드에서만 접근 가능하지만 추상 클래스여서 인스턴스화 할 수 없음)

 

때문에 필드가 외부로부터 보호되지만 다른 자식 클래스에서 사용되기를 원한다면

private을 쓰지 않아야 한다. -> 이 경우 protected를 사용할 수 있다.

 

protected

abstract class User {
  constructor (
    private firstName: string, 
    private lastName: string, 
    private nickname: string
  ){}
  abstract getNickName(): void
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Player extends User {
  getNickName() {
    console.log(this.nickname);  // User를 상속하면 접근 가능
  }
}

const nico = new Player("nico", "las", "니꼬");
nico.getFullName();
nico.firstName  // Error! 클래스 밖에서 접근 불가

 

 

728x90