본문 바로가기

TypeScript

TypeScript로 이해하는 객체지향

 

객체지향적으로 커피머신을 만들어보자.

 

목표

TypeScript로 짜여진 예시를 통해 객체지향의 핵심 개념 (캡슐화, 추상화, 상속, 다형성)을 모두 이해한다.

 

Step1. 커피머신 클래스 만들기

커피머신에 필요한 변수와 함수에는 어떤 것들이 있을까?

// 커피를 타입으로 선언
type Coffee = {
  shots: number;
  hasMilk: boolean;
};

class CoffeeMachine {
  // 변수 선언
  static BEANS_GRAM_PER_SHOT: number = 7;	// 클래스 레벨
  coffeeBeans: number = 0;			// 인스턴스 레벨
  
  // 커피머신 객체를 만들 때 호출되는 생성자
  constructor(coffeeBeans: number) {
    this.coffeeBeans = coffeeBeans;
  }
	
  // 함수 정의
  // 커피 만들기 함수. 샷을 인자로 받아서 커피를 리턴한다.
  makeCoffee(shots: number): Coffee {
    if (this.coffeeBeans < shots * CoffeeMachine.BEANS_GRAM_PER_SHOT) {
      throw new Error('Not enough coffee beans!');
    }
    this.coffeeBeans -= shots * CoffeeMachine.BEANS_GRAM_PER_SHOT;
    return {
      shots,
      hasMilk: false,
    };
  }
}

const machine = new CoffeeMachine(32);	// 커피머신 객체 생성
console.log(machine);			// CoffeeMachine { coffeeBeans: 32 }

 

Step 2. 클래스 변수 캡슐화 하기 (Encapsulation)

클래스 외부에서 변수를 임의로 수정할 수 없도록 캡슐화 한다.

수정 필요한 변수는 함수를 통해서만 접근 가능하다.

 

  • public: 외부에서 접근 가능
  • private: 외부에서 접근 불가
  • protected: 상속받은 자식에서만 접근 가능
private static BEANS_GRAM_PER_SHOT: number = 7;
private coffeeBeans: number = 0;

// coffeeBeans 변수를 수정하는 함수
fillCoffeeBeans(beans: number) {
  if (beans < 0) {
    throw new Error('value for beans should be greater than 0');
  }
  this.coffeeBeans += beans;
}

 

Step 3. 인터페이스로 추상화 하기 (Abstraction)

인터페이스는 마치 커피머신의 설명서 같은 것이다.
인터페이스를 통해 클래스에 어떠한 함수가 있는지 파악할 수 있다.

하나의 클래스는 여러 인터페이스를 구현할 수 있다.

※ 인터페이스는 앞에 I를 붙여서 표현하는 방법이 있다.

※ A implements B = A는 B를 구현한다.

interface ICoffeeMachine {
  makeCoffee(shots: number): Coffee;
}

class CoffeeMachine implements ICoffeeMachine {
// ...

 

Step 4. 상속으로 다양한 커피머신 만들기 (Inheritance)

커피머신을 상속하는 라떼머신을 만들어보자.

super를 통해 부모 클래스의 것을 가져다 쓸 수 있다.

※ A extends B = A는 B를 확장한다.

class LatteMachine extends CoffeeMachine {
  private milk: number = 0; 
  
  constructor(beans: number, milk: number) {
    super(beans);
    this.milk = milk;
  }
  
  makeCoffee(shots: number): CoffeeCup {
    const coffee = super.makeCoffee(shots);
    return {
      ...coffee,
      hasMilk: true,
    };
  }
}

 

Step 5. makeCoffee 함수로 다형성 이해하기 (Polymorphism)

makeCoffee 함수는 커피머신과 라떼머신 둘 다 갖고있다.

그러나 그 내용은 다르다. 이것이 다형성의 개념이다.

아래 forEach문은 커피머신이 만든 커피와와 라떼머신이 만든 커피를 각각 출력한다.

const machines = {
  new CoffeeMachine(16),
  new LatteMachine(16, 5),
};

machines.forEach(machine => {
  console.log(machine.makeCoffee(1));
});