TypeScript -OOP programing -1

0

TypeScript - OOP Programing

Typescript 드림코딩 oop 강의를 참조하여 정리하였습니다.

1. 객체지향 프로그래밍이란?

프로그래밍 패러다임 중 하나로 의미 그대로 객체 중심적인 사고로 객체를 기반으로한 프로그래밍을 말한다. 클래스와 객체의 개념에 의존하는 프로그래밍의 패러다임이며 함수지향 프로그래밍과 더불어 오늘날 대표적인 프로그래밍 방식으로 JAVA, C# 등의 언어들에서 많이 쓰이고 있다.

객체지향의 원칙

객체 지향의 중요한 원칙에 대해 알아보자!

  • 캡슐화(Encapsulation)
  • 추상화(abstraction)
  • 상속(inheritance)
  • 다형성(polymorphism)

Encapsulation

객체의 속성과 메서드를 하나로 묶고, 외부에 보일 필요없는 데이터들은 감추어 은닉화한다라고 생각하면 된다.

예를 들어 캡슐 알약을 생각해보면, 우리는 캡슐안에 어떤 성분이 있는지 생각없이 하나의 캡슐만 먹으면 된다. 이와 마찬가지로 서로 관련 있는 데이터와 함수를 한 오브젝트 안에 담아두고 외부에서 보일 필요 없는 데이터는 은닉화 시킬 수 있다.

Abstraction(추상성)

예를 들어 커피 머신이 있다고 가정하면, 커피머신이 어떻게 동작되어지는 모르지만, 캡슐과 버튼만 누르면 에스프레소가 나온다

이처럼 추상화를 통해 외부에서는 내부에서는 어떻게 구현 되어있는지 여부는 모르고 외부에서 구현된 interface 함수를 이용해서 객체를 사용 할 수 있다.

Inhertiance(상속)

의미 그대로 부모님이 자식에게 물려 주 듯이 상위 클래스의 공통적인 특성을 하위 클래스가 물려받아 확장할 수 있는 것을 의미한다.

일반적인 우릐 가족 계층도에서 볼 수 있는 그런 상속의 개념이 아니라 동물- 포유류 종과 같은 개념이라고 보면 된다.

고래을 예시로 들면 동물에는 파충류 , 포유류, 곤충류 등등이 있고, 동물에서 - 포유류 인 셈으로 볼 수 있다.

Polymorphism(다형성)

다양한 형태라는 영어 사전적 의미로 하나의 객체가 여러가지 타입을 있는 것을 의미한다.

예를 들어, 커피 기계의 경우 브루드 커피든 ,캡슐 커피 머신이든, 에스프레소 머신이든 makeCoffee()라는 공통 함수를 이용해서 어떤 머신이든 상관없이 커피를 내릴 수 있다고 생각하면 좋다.

2. 절차 지향적으로 커피 기계 만들어보기

// makeCoffee라는 함수를 구현해보자! 얼마나 많은 샷을 받아 오는지 인자로 받고 그 샷에 따라 커피를 만들어주는 함수라고 하자!

type CoffeeCup = {
  shots: number;
  hasMilk: boolean;
};

// 하나의 샷에 소모되는 커피그램은 16g. esperesso 1shot이라고 가정
const BEANS_GRAMM_PER_SHOT: number = 16;

// 우리가 가지고 있는 커피 콩의 양, 현재는 0이라고 가정
let coffeeBeans: number = 0;


function makeCoffee(shots: number): CoffeeCup {
  // 우리가 가지고 있는 커피콩의 양의 샷의 숫자와 BEANS_GRAMM_PER_SHOT의 곱보다 작으면 error
  if (coffeeBeans < shots * BEANS_GRAMM_PER_SHOT) {
    throw new Error('Not enough coffee beans!');
  }
  
  coffeeBeans -= shots * BEANS_GRAMM_PER_SHOT;
  // 정상적으로 작동시 아래의 객체를 리턴
  return {
    shots,
    hasMilk: false,
  };
}
		
// 커피콩의 숫자를 늘려준다. 현재 커피량이 0으로 할당해주었기에 먼저 커피콩을 할당해준다.
coffeeBeans += 3 * BEANS_GRAMM_PER_SHOT;
const coffee = makeCoffee(2)
console.log(coffee); // { shots: 2, hasMilk: false }

객체지향적으로 코딩하기

  • 클래스를 만들어 객체의 청사진을 만들고 서로 관련 있는 데이터나 함수를 묶어 놓을 수 있다.
  • 위의 절차 지향적으로 만든 코드를 바꿔보자!
type CoffeeCup = {
  shots: number;
  hasMilk: boolean;
};

class CoffeeMaker {
  // 멤버변수, 속성을 클래스 안으로 넣어 줄 수 있다. 
  // BEANS_GRAMM_PER_SHOT은 클래스 안에서 생성된 고정 된 값이기 때문에 
  // 인스턴스 생성시 마다 중복적으로 생성되기 때문에 메모리 낭비가 심하다. => static을 사용
  BEANS_GRAMM_PER_SHOT: number = 16;
  coffeeBeans: number = 0;

  // constructor를 생성해서 class를 가지고 obejct instance를 만들 때 항상 호출이 되도록 할 수 있다.
  // coffeBeans에 그램을 할당해주어야 하기 때문에 construtor를 생성자를 통해 지정해 줄 수 있다.
  constructor(coffeeBeans: number) {
    this.coffeeBeans = coffeeBeans;
  }

  makeCoffee(shots: number): CoffeeCup {
    if (this.coffeeBeans < shots * this.BEANS_GRAMM_PER_SHOT) {
      throw new Error('Not enough coffee beans!');
    }
    this.coffeeBeans -= shots * this.BEANS_GRAMM_PER_SHOT;
    return {
      shots,
      hasMilk: false,
    };
  }
}

static

  • 클래스 내부에서 데이터 항상 고정으로 지정된 데이터 값들이 필요할 수 있다. 이런 경우와 클래스 레벨에서 함수를 호출하고 싶은 경우 사용할 수 있다.
type CoffeeCup = {
  shots: number;
  hasMilk: boolean;
};

class CoffeeMaker {
  static BEANS_GRAMM_PER_SHOT: number = 7; // class level - 클래스와 연결되어 있어서 오브젝트마다 생성되지 않음!
  coffeeBeans: number = 0; // instance(object) level

  constructor(coffeeBeans: number) {
    this.coffeeBeans = coffeeBeans;
  }
  // static을 사용하여 클래스 내부에서 스스로 인스턴스를 만들어서 리턴하는 메서드를 정의할 수 있다.
  static makeMachine(coffeeBeans: number): CoffeeMaker {
    return new CoffeeMaker(coffeeBeans);
  }

  makeCoffee(shots: number): CoffeeCup {
    // static으로 선언한 멤버변수는 this대신에 클래스의 이름을 붙혀줘야한다.
    if (this.coffeeBeans < shots * CoffeeMaker.BEANS_GRAMM_PER_SHOT) {
      throw new Error('Not enough coffee beans!');
    }
    this.coffeeBeans -= shots * CoffeeMaker.BEANS_GRAMM_PER_SHOT;
    return {
      shots,
      hasMilk: false,
    };
  }
}

//before makeMahchine이란 static 메소드 정의 전
const maker = new CoffeeMaker(23);
console.log(maker); // CoffeeMaker { coffeeBeans: 23 } // 동일하게 커피빈은 찍히지만 new 생성자를 통해 생성해줘야함!

// static을 사용하기 위해 클래스의 이름으로 접근하는 예
const maker3 = CoffeeMaker.makeMachine(23); // new 키워드 따로 없이 static 메소드 호출을 통해 결과를 동일하게 낼 수 있다.
console.log(maker3); // CoffeeMaker { coffeeBeans: 23 }

/**
 * Math.max(), Math.min() 등이 static으로 선언된 메소드들을 불러오는 것이 static의 예시라 할 수 있다.
 */

Reference

드림코딩엘리 typescript

profile
문과생 개발자되다

0개의 댓글