type CoffeeCup = {
shots: number;
hasMilk?: boolean;
hasSugar?: boolean;
};
*// interface*
interface CoffeeMakerA {
makeCoffee(shots: number): CoffeeCup;
}
*// Class 1*
*// Parent Class : CoffeeMaker ( 추상 클래스 ) ★*
abstract class CoffeeMaker implements CoffeeMakerA {
private static BEANS_GRANS_PER_SHOT = 7;
constructor(private coffeeBeans: number,) {
this.coffeeBeans = coffeeBeans;
}
fillCoffeeBeans(beans: number) {
if (beans < 0) {
throw new Error('beans not enoughf');
}
this.coffeeBeans += beans;
}
private grindBeans(shots: number) {
console.log(`grinding beans for ${shots}`);
if (this.coffeeBeans < shots * CoffeeMaker.BEANS_GRANS_PER_SHOT) {
throw new Error('Not enough coffee beans!');
}
this.coffeeBeans -= shots * CoffeeMaker.BEANS_GRANS_PER_SHOT;
}
private preheat(): void {
console.log('heating up...🔥');
}
*// 추상 메서드 선언 ★*
protected abstract extract(shots: number): CoffeeCup;
public makeCoffee(shots: number): CoffeeCup {
this.grindBeans(shots);
this.preheat();
const coffee = this.extract(shots); *// 자식 클래스에서 extract 함수 오버라이딩*
const addsugar = this.sugar.addSugar(coffee);
*return* this.milk.makeMilk(addsugar);
}
}
*// Class 2 : CoffeeLatteMachine ( 자식 클래스 )*
class CoffeeLatteMachine implements CoffeeMaker {
constructor(coffeeBeans: number, public serialNumber: string) {
super(coffeeBeans);
}
private steamMilk(): void {
console.log('Steaming some milk... 🥛');
}
*// 추상 메서드 오버라이딩 ★*
extract(shots: number): CoffeeCup {
this.steamMilk():
console.log(`Pulling ${shots} shots...☕`);
*return* {
shots: shots,
hasMilk: true,
}
}
}
*// Class 3 : SweetCoffeeMaker ( 자식 클래스 )*
class SweetcoffeeMaker implements CoffeeMaker {
*// 추상 메서드 오버라이딩 ★*
extract(shots: number): CoffeeCup {
console.log(`Pulling ${shots} shots...☕`);
*return* {
shots: shots,
hasMilk: false,
}
}
}
*// 호출 유형 & 방법 예시 기억해 두기 ★★★*
*// Milk*
const machines = [
new CoffeeLatteMachine(24, 'ssss-1'),
new SweetCoffeeMaker(24),
new CoffeeLatteMachine(24, 'ssss-2'),
new SweetCoffeeMaker(24),
];
machines.forEach(machine => {
console.log('----------------------');
machine.makeCoffee(1);
});
[ 추상 클래스 - Abstract ]
abstract 로 만들어진 클래스 자체는 (new)object 를 생성할 수 없는 클래스인 추상적인 클래스다.
공통적으로 사용하는 기능(함수)은 추상 클래스에서 정상적인 메소드처럼 선언할 수 있으며, 내부적으로 쓰인다면 private, 외부적으로 쓰인다면 public을 사용하는 등 기존 class 와 동일하나, 그러나 자식 클래스의 클래스마다 실질적인 기능을 구현하는 abstract 기능(함수)들은 추상 클래스에서는 기본 선언만, 자식 클래스에서는 선언 및 구현을 해야한다. 즉 오버라이딩 한다.
이런 abstract 함수를 자식 클래스에서 구현하지 않으면 에러가 발생한다.
이렇게 abstract 클래스를 이용하면 조금 더 안전하게, 의도한 대로 부모클래스(추상클래스)에서는 공통적인 기능들을 수행하고, 달라져야 되는 것만 상속되는 클래스에게 반드시 구현하라고 강조할 수 있다.