[TypeScript] #03. Classes And Interfaces

ZenTechie·2023년 6월 3일
0

TypeScript

목록 보기
3/3
post-thumbnail

클래스(Class)

Class (기본 클래스)

TS에서 일반적인 클래스는 다음과 같이 만들 수 있다.

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

const lunar = new Player("lunar", "moon", "zentechie");

lunar.firstName = "ddd"; // 에러

여기서 firstNameprivate이므로, lunar.firstName = "ddd";에서 에러가 발생한다.
(private을 가지고 있다면, 임의로 수정을 할 수가 없다.)

JS에서는 이 코드가 아래와 같이 표현된다.

class Player {
    constructor(firstName, lastName, nickname) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.nickname = nickname;
    }
}
const lunar = new Player("lunar", "moon", "zentechie");

lunar.firstName = "ddd";

보다시피 privatepublic이 사라졌다. 그리고 this가 사용됐다.
TS에서는 번거롭게 이러한 this사용하지 않아도 내부적으로 처리해준다.
또한, lunar.firstName = "ddd"; 에서 에러가 발생하지 않는다.

Abstract Class (추상 클래스)

추상 클래스는 다른 클래스가 상속받을 수 있는 클래스이다.
직접적으로 추상 클래스의 새로운 인스턴스만들 수는 없다. 상속받는 클래스는 extends사용해서 상속받는다.

abstract class User { // 추상 클래스
    constructor (
        private firstName:string,
        private lastName:string,
        public nickname:string
    ) {}
}
class Player extends User {
    
}

const lunar = new User("lunar", "moon", "zentechie"); // 에러

추상 클래스의 메소드를 알아보자.

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 lunar = new Player("lunar", "moon", "zentechie");
lunar.getFullName() // 에러

보다시피 풀네임을 반환하는 getFullName()이 메소드이다. 우리는 Player의 인스턴스에서 getFullName()을 호출할 수 있다.(→ User 클래스를 상속받았기 때문이다.)

추상 메소드도 접근 제한자를 설정할 수 있는데, 프로퍼티와 마찬가지로 private으로 설정하게 되면 더 이상 해당 메소드를 접근할 수 없게된다.

즉, privatepublic이 프로퍼티 뿐만 아니라 메소드에서도 작동한다.

추상 메소드도 알아보자. 추상 메소드는 일반 메소드랑 다르게 선언만 하고 구현은 하지 않는다.

abstract class User {
    constructor (
        protected firstName:string,
        protected lastName:string,
        protected nickname:string
    ) {}
    getFullName() {
        return `${this.firstName} ${this.lastName}`
    }
    abstract getNickName():void
}
class Player extends User {
    getNickName() {
      console.log(this.nickname)
    }
}

추상 메소드는 추상 클래스를 상속받는 모든 클래스들이 구현을 해야하는 메소드를 의미한다.
여기서는 Player 클래스가 해당되겠다.

보다시피 추상 메소드인 getNickName()은 선언만 하고 구현은 하지 않았다.
User를 상속받는 Player 클래스에서 구현을 진행한다.

접근 제한자

알아둬야 하는 개념이다.
접근 제한자에 따라서, 어떤 상황에서 접근할 수 있는지 없는지가 달라진다.

구분선언한 클래스 내상속받은 클래스 내인스턴스
private⭕️
protected⭕️⭕️
public⭕️⭕️⭕️

인터페이스(interface)

type의 용도

  • 오브젝트의 모양을 묘사하는데 사용한다.
    ex. type Foods = { name: string, def: string }
  • 타입 alias 만드는데 사용한다.
    ex. type Food = string
  • 타입이 특정 값을 가지도록 제한하는데 사용한다.
    ex. type Food = "한식" | "일식" | "중식"

interface의 용도

type과는 약간의 차이점이 존재하는데, 인터페이스는 오직 한가지의 용도로만 사용된다.

'오브젝트의 모양을 묘사'

TS에서 오브젝트의 모양을 알려주는 방법은 typeinterface 2가지 이다.

for type

type Foods = { ... }

for interface

interface Foods { ... }

interface가 가지는 다른 기능들도 살펴보자.

  1. interface상속의 개념을 활용할 수도 있다.
interface Foods { name : string }
interface Food extends Foods {}
  1. 다수의 property축적시킬 수 있다.
interface Person {
    name:string
}

interface Person {
    age:number
}

interface Person {
    sex:string
}

const person: Person = {
    name:"lunarmoon",
    age: 99,
    sex: "alien"
} // 3개의 interface가 합쳐진다.

interface객체지향 프로그래밍의 개념을 활용해서 디자인되었고, 오로지 오브젝트의 모양을 설명해주는 용도로만 사용된다.

typeinterface 키워드에 비해 좀 더 활용할 수 있는게 많다. → 좀 더 유연하다.

not 추상 클래스, but 인터페이스

추상 클래스가 있다고 하자. 이를 JS로 변환하게 된다면 추상 클래스 JS파일에 변환되어 남게된다.

하지만 인터페이스를 사용해서 implements를 한다면, JS로 변환했을 시 코드가 남지 않는다.
(JS에서 인터페이스와 implements를 지원하지 않기 때문이다.)

interface & implements를 사용해서 코드 최적화를 시킬수 있다.

기능적인 부분에서 abstractinterface & implements완전 동일한 기능을 수행하지만, 코드 최적화를 해야한다면 인터페이스를 사용하는 것이 좋다.

profile
데브코스 진행 중.. ~ 2024.03

0개의 댓글