[TIL #40] TypeScript 객체 지향 프로그래밍

Bora.K | 권보라·2023년 12월 14일
0

TIL

목록 보기
40/51
post-thumbnail

오늘 한 일


  • [TypeScript] 문법 종합반 강의

학습 내용


객체 지향 프로그래밍

1. 클래스

(1) 클래스란?

클래스는 객체 지향 프로그래밍(OOP)의 핵심 구성 요소 중 하나로, 객체를 만들기 위한 틀(템플릿)이다.

  • 객체들이 공통으로 가지는 속성(객체의 성질)과 메서드(객체의 성질 변화 및 기능)를 정의
  • 객체는 클래스의 인스턴스(instance)

(2) 클래스 정의 방법

  • class 키워드를 사용하여 클래스 정의
  • new 키워드를 사용하여 객체 생성
class Person {
  name: string;
  age: number;

// 생성자
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  sayHello() {
    console.log(`안녕하세요! 제 이름은 ${this.name}이고, 나이는 ${this.age}살입니다.`);
  }
}

const person = new Person('Spartan', 30);
person.sayHello();
  • 생성자 constructor
    - 클래스의 인스턴스를 생성하고 초기화할 때 한 번만 사용되는 메서드
    - 클래스 내에 오직 하나만 존재할 수 있다.

(3) 클래스 접근 제한자

  • public
    • 클래스 외부에서도 접근 가능한 접근 제한자
    • 기본적으로 접근 제한자는 public
  • private
    • 클래스 내부에서만 접근 가능한 접근 제한자
    • 클래스의 속성을 보거나 편집하고 싶다면 별도의 getter/setter 메서드를 준비
  • protected
    • 클래스 내부와 해당 클래스를 상속받은 자식 클래스에서만 접근 가능한 접근 제한자

2. 상속

(1) 상속이란?
상속은 객체 지향 프로그래밍에서 클래스 간의 관계를 정의하는 중요한 개념으로,
상속을 통해 기존 클래스의 속성과 메서드를 물려받아 새로운 클래스를 정의할 수 있다.

  • extends 키워드 사용
  • super 부모 클래스의 생성자 호출
  • 오버라이딩 : 부모의 함수 동작을 새롭게 정의하는 것
class Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  makeSound() {
    console.log('동물 소리~');
  }
}

// 상속
class Dog extends Animal {
  age: number;

  constructor(name: string) {
    super(name);
    this.age = 5;
  }

  makeSound() {
    console.log('멍멍!'); // 오버라이딩(함수의 동작을 새롭게 정의)
  }

  eat() {
    console.log('강아지가 사료를 먹습니다.'); // Dog 클래스만의 새로운 함수 정의
  }
}

class Cat extends Animal { // Animal과 동일한 속성으로 생성
}

const dog = new Dog('누렁이');
dog.makeSound(); // 출력: 멍멍!

const cat = new Cat('야옹이');
cat.makeSound(); // 출력: 동물 소리~

(2) 서브타입, 슈퍼타입

  • 서브타입 / 슈퍼타입
    위 예시에서 animal은 슈퍼타입, dog, cat은 서브타입

  • upcasting : 서브타입 → 슈퍼타입으로 변환

let dog: Dog = new Dog('또순이');
let animal: Animal = dog; // 슈퍼타입 변수에 대입하여 upcasting
animal.eat(); // 에러. 슈퍼타입(Animal)으로 변환이 되어 eat 메서드 호출 불가능
  • downcasting : 슈퍼타입 → 서브타입으로 변환
let animal: Animal;
animal = new Dog('또순이');

let realDog: Dog = animal as Dog; // as로 명시적으로 타입 변환
realDog.eat(); // 서브타입(Dog)로 변환이 되었기 때문에 eat 메서드 호출 가능

3. 추상 클래스

인스턴스화를 할 수 없는( new 로 객체를 생성할 수 없는) 클래스

  • 상속을 통해 자식 클래스에서 메서드를 제각각 구현하도록 하는 용도로 사용
  • 핵심 기능의 구현은 자식 클래스에 위임
  • abstract 키워드를 사용하여 정의
  • 추상 클래스는 1개 이상의 추상 함수가 있는 것이 일반적
// 추상 클래스 정의
abstract class Shape {
  abstract getArea(): number; // 추상 함수 정의(자식 클래스에서 핵심 기능 구현)

  printArea() {
    console.log(`도형 넓이: ${this.getArea()}`);
  }
}

// 자식 클래스
class Circle extends Shape {
  radius: number;

  constructor(radius: number) {
    super();
    this.radius = radius;
  }

  getArea(): number { // 자식 클래스에서 필수로 구현해야 함
    return Math.PI * this.radius * this.radius; // 원의 넓이를 구하는 공식
  }
}

→ 각 도형마다 넓이를 구하는 공식이 다르기 때문에, 각각의 자식 클래스에서 핵심 기능을 구현

4. 인터페이스

(1) 인터페이스란?
객체가 가져야 하는 속성과 메서드를 정의한다.
인터페이스를 사용하면 코드의 안정성과 유지 보수성을 향상시킬 수 있다.

(2) 추상 클래스와 인터페이스의 차이

추상클래스인터페이스
구현부 제공 여부클래스의 기본 구현 제공객체의 구조만 정의
상속 메커니즘단일 상속 지원다중 상속 지원
구현 메커니즘추상 클래스를 상속받은 자식클래스는
반드시 추상함수 구현
인터페이스를 구현하는 클래스는
정의된 모든 메서드 전부 구현

5. 객체 지향 설계 원칙 - S.O.L.I.D

(1) S(SRP. 단일 책임 원칙)
클래스는 하나의 책임만 가져야 하며, 다른 액션을 해서는 안된다.

(2) O(OCP. 개방 폐쇄 원칙)
클래스의 기존 코드를 변경하지 않고도 기능을 확장할 수 있어야 하며, 수정에 대해서는 닫혀 있어야 한다. → 인터페이스나 상속을 통해 해결

(3) L(LSP. 리스코프 치환 원칙)
서브타입은 기반이 되는 슈퍼타입을 대체할 수 있어야 한다.
자식 클래스는 부모 클래스의 기능을 수정하지 않고도 부모 클래스와 호환이 되어야 한다.

(4) I(ISP. 인터페이스 분리 원칙)
클래스는 자신이 사용하지 않는 인터페이스의 영향을 받지 않아야 한다.
인터페이스를 필요한 만큼만 정의하고, 클래스는 필요한 인터페이스들을 구현한다.

(5) D(DIP. 의존성 역전 원칙)
하위 수준 모듈(구현 클래스)보다 상위 수준 모듈(인터페이스)에 의존해야 한다.


오늘의 회고


TypeScript 강의를 5주차까지 다 들었는데, 개념이 너무 헷갈린다. type, class, interface 각각 차이가 아직 명확하게 머릿속에 들어오지 않는다. 다양한 예제를 적용해봐야 좀 감이 잡힐 것 같다. 내일 과제를 해보면서 다시 개념을 정리 해봐야 할 것 같다. 어렵다...


내일 할 일


  • [개인 과제] TypeScript로 todo List 구현
profile
Frontend Engineers

0개의 댓글