-
인터페이스 ( 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(); }
'Develop > TypeScript' 카테고리의 다른 글
[Typescript] Could not find a declaration file for module 'react' - 에러 해결 (0) 2021.03.19 [TypeScript] 타입(type) vs 인터페이스(interface) (0) 2021.03.16 [TypeScript] 객체지향의 특징 1편 ( 캡슐화[Encapsulation] , Getter & Setter ) (0) 2021.03.11 [TypeScript] 객체지향이란(What is Object Oriented Programing) ? (0) 2021.03.08 댓글