• [TypeScript] 객체지향의 특징 2편 Interface

    2021. 3. 11.

    by. KimBangg

    인터페이스 ( Interface ) 

     

    1-1 인터페이스가 뭔가요?

     

    인터페이스 들으면 어떤 느낌이 가장 먼저 떠오르시나요?

     

    유저와 서버를 연결 해준다는UI(User Interface) 가 가장 먼저 떠오르는데 오늘 배워 볼 인터페이스는 다소 다른 느낌을 가지고 있습니다.

     

    실제로 학부과정에서 배운 자바를 배울 때에도 : 인터페이스 = 법 || 룰" 정도로 배워왔는데, 다시 배우는 입장에서도 가장 적합한 예시라고 생각이 듭니다.

     

    역시 말로만 하면 이해가 어려우니 하단의 코드와 설명을 통해 자세히 이야기 해보겠습니다.

     

    * 인터페이스는 어느정도 추상화(Abstraction)와의 연관성도 있어 여기서 잠깐 설명 드리고 가겠습니다 :)

     

     

    1-2 추상화란 뭔가요?

     

    추상화란 쉽게 말해서 작동원리를 알지 못해도 사용 할 수 있게끔 만들어주는 것을 의미합니다.

    저희의 실제 생활 속에서도 컴퓨터 / 자동차 등 어려운 기기의 작동원리를 배우지 않아도 다룰 수 있는 것이 추상화 덕분이죠 :)

     

    개발의 단계에서도 추상화는 반드시 필요한데 ! 그 이유는 위에서 언급된 것들과 같이 "사용의 편리함"을 갖추기 위해서 라고 생각합니다.

     

    이러한 추상화를 이루어 낼 수 있는 방법은 제가 아는 방법으로는 2가지 정도가 존재합니다.

     

    1-2-1 Private 

    클래스 안에서 유저 또는 개발자에게 보여 주고 싶은 object가 아니라면 모두 private을 걸어서 사용 하지 못하게 하는 방법이 있습니다.

     

    1-2-2 Interface 

    2번째 방법은 저희가 계속 다루고자 하는 인터페이스 인데요 ! 인터페이스의 목적은 이 곳을 통해 확인 하였으니 이제 '이해'를 위해 코드를 살펴 보러 가겠습니다! 

     

     

    1-3 코드 및 예시 ( 추상화 )

     

    제가 짠 코드 속에는 CoffeeMachine 이라는 Class가 존재하는데 ,하지만 여기에는 굉장히 많은 function이 존재합니다.

     

    그렇기 떄문에 CoffeeMachine을 사용하는 유저의 입장에서는 어떤 순서로, 무엇을 써야할지에 대해 굉장한 어려움을 겪을 수 있는데 이를 interface인 CoffeeMaker & CommercailCoffeemaker를 통해 줄여주고자 합니다.

     

    CoffeeMaker라는 인터페이스에서는 makeCoffee 라는 함수를,  CommercailCoffeemaker에서는 makeCoffee,

    fillCoffeeBeans, Clean 함수를 규칙으로 설정해두어 이러한 interface를 implement 하는 class에게 룰을 제공하고 있습니다.

     

    {
      type CoffeeCup = {
        shots: number;
        hasMilk: boolean;
      };
    
      interface CoffeeMaker {
        makeCoffee(shots: number): CoffeeCup;
      }
    
      interface CommercialCoffeeMaker {
        makeCoffee(shots: number): CoffeeCup;
        fillCoffeeBeans(beans: number): void;
        clean(): void;
      }
    
      class CoffeeMachine implements CoffeeMaker, CommercialCoffeeMaker {
        private static BEANS_GRAM_PER_SHOT: number = 7; // class level => 오브젝트별로 새로 생성되지 않는다.
        private coffeeBeans: number = 0; // istance(object)
    
        private constructor(coffeeBeans: number) {
          this.coffeeBeans = coffeeBeans * CoffeeMachine.BEANS_GRAM_PER_SHOT;
        }
    
        // static을 통해 Object를 열어 주었다는건, 생성자를 통한 접근을 원치 않는 것.
        // 그리하여 constructor를 private으로
        static makeMachine(coffeeBeans: number): CoffeeMachine {
          return new CoffeeMachine(coffeeBeans);
        }
    
        fillCoffeeBeans(beans: number) {
          if (beans < 0) {
            throw new Error('value for beans should be greater than zero');
          }
          this.coffeeBeans += beans * CoffeeMachine.BEANS_GRAM_PER_SHOT;
        }
    
        private grindBeans(shots) {
          console.log(`grinding beans for $`);
          if (this.coffeeBeans < shots * CoffeeMachine.BEANS_GRAM_PER_SHOT) {
            throw new Error('Not enought coffee beans!');
          }
          this.coffeeBeans -= shots * CoffeeMachine.BEANS_GRAM_PER_SHOT;
        }
    
        private preheat(): void {
          console.log('heating machine before extracting Shots..');
        }
    
        private extract(shots: number): CoffeeCup {
          console.log(`Pulling ${shots} shots...`);
          return {
            shots,
            hasMilk: false,
          };
        }
    
        makeCoffee(shots: number): CoffeeCup {
          this.grindBeans(shots);
          this.preheat();
          return this.extract(shots);
        }
    
        clean(): void {
          console.log('cleaning the machine');
        }
      }
    
      class AmateurUser {
        constructor(private machine: CoffeeMaker) {}
        makeCoffee() {
          const coffee = this.machine.makeCoffee(2);
          console.log(coffee);
        }
      }
      class ProBarista {
        constructor(private machine: CommercialCoffeeMaker) {}
        makeCoffee() {
          const coffee = this.machine.makeCoffee(2);
          console.log(coffee);
          this.machine.fillCoffeeBeans(45);
          this.machine.clean();
        }
      }
    
      //const maker = new CoffeeMaker(3);
      // Constructor를 이용 가능하게 한 경우.
      const maker: CoffeeMachine = CoffeeMachine.makeMachine(32);
      maker.fillCoffeeBeans(32);
      // 추상화를 위해 필요한 함수 외에는 private으로 제한
      // 또는 Interface & implemen로 구현
      maker.makeCoffee(2);
    
      const maker2: CommercialCoffeeMaker = CoffeeMachine.makeMachine(32);
      maker2.clean();
      maker2.makeCoffee(2);
    
      const amateur = new AmateurUser(maker);
      const pro = new ProBarista(maker);
    
      pro.makeCoffee();
    }
    

     

    댓글