8/4 til 타입스크립트 강의

이승준·2023년 8월 6일
0

5주차

🖥️클래스

  • 객체를 만드는 틀
  • 객체지향프로그래밍의 핵심 요소
  • 객체 == 클래스의 인스턴스

클래스의 구성요소

  • 속성과 메서드

사용사례

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??

  • 생성자는 클래스의 인스턴스를 생성하고 초기화하는데 사용되는 특별한 메서드에요.
  • 생성자는 클래스 내에서 constructor라는 이름으로 정의됩니다.
  • 생성자는 인스턴스를 생성할 때 자동으로 호출되고요.
  • 생성자는 클래스 내에 오직 하나만 존재할 수 있습니다.
  • 보통, 생성자로 객체 속성을 초기화 하는것 뿐 아니라 객체가 생성이 될 떄 꼭 되어야 하는 초기화 로직을 집어넣기도 해요!
    • 예를 들어, DBConnector라는 클래스가 있다면 이 클래스 타입의 객체가 생성이 될 때 생성자에서 DB 연결을 미리 해주면 편할거에요!

접근제한자

  • public
    • 클래스 외부에서도 접근이 가능한 접근 제한자입니다.
    • 접근 제한자가 선언이 안되어있다면 기본적으로 접근 제한자는 public 입니다.
    • 보통은 클래스의 함수 중 민감하지 않은 객체 정보를 열람할 때나 누구나 해당 클래스의 특정 기능을 사용해야 할 때 많이 쓰여요!
  • private
    • 클래스 내부에서만 접근이 가능한 접근 제한자입니다.
    • 보통은 클래스의 속성은 대부분 private으로 접근 제한자를 설정해요.
      • 즉, 외부에서 직접적으로 객체의 속성을 변경할 수 없게 제한하는 것이죠!
    • 클래스의 속성을 보거나 편집하고 싶다면 별도의 getter/setter 메서드를 준비해놓는 것이 관례에요!
  • protected
    • 클래스 내부와 해당 클래스를 상속받은 자식 클래스에서만 접근이 가능한 접근 제한자입니다.

🖥️상속

  • 상속은 객체 지향 프로그래밍에서 클래스 간의 관계를 정의하는 중요한 개념입니다!
  • 상속을 통해 기존 클래스의 속성과 메서드를 물려받아 새로운 클래스를 정의할 수 있어요.

사용사례

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('멍멍!'); // 부모의 makeSound 동작과 달라요!
  }

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

class Cat extends Animal { // Animal과 다를게 하나도 없어요!
}

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

const cat = new Cat('야옹이');
cat.makeSound(); // 출력: 동물 소리~
  • super 키워드는 자식 클래스가 부모 클래스를 참조하는데 사용하는 키워드에요!
    • 즉, 자식 클래스에서 생성자를 정의할 때 부모 클래스의 생성자를 호출해야 하는데 이 때 씁니다!

💡 자식 클래스가 부모 클래스의 생성자나 메서드를 그대로 사용하고 싶다면 자식 클래스에선 다시 작성하지 않아도 됩니다! → Cat 클래스를 보세요!

  • Dog 클래스는 부모의 makeSound 함수의 동작을 새롭게 정의해요. 이것을 오버라이딩이라고 합니다.

서브타입 vs 슈퍼타입

upcasting, downcasting

  1. upcasting
let dog: Dog = new Dog('또순이');
let animal: Animal = dog; // upcasting 발동! 
animal.eat(); // 에러. 슈퍼타입(Animal)으로 변환이 되어 eat 메서드를 호출할 수 
없어요! 
  1. downcasting
let animal: Animal;
animal = new Dog('또순이');

let realDog: Dog = animal as Dog;
realDog.eat(); // 서브타입(Dog)로 변환이 되었기 때문에 eat 메서드를 호출할 수 있죠!

음… 뭐 upcasting이란 기술이 있는 것은 알겠는데 대체 왜 이게 필요한거에요?

  • upcasting이 필요한 이유는 서브타입 객체를 슈퍼타입 객체로 다루면 유연하게 활용할 수 있기 때문이에요!
    • 예를 들어, Dog, Cat, Lion 그리고 기타 등등 다양한 동물을 인자로 받을 수 있는 함수를 만들고 싶다면?
    • 올바른 선택: 아! Animal 타입의 객체를 받으면 모두 다 받을 수 있겠구나!
    • 잘못된 선택: 아! union으로 새로운 타입을 만들어서 해당 타입의 객체를 받게해야겠구나!

🖥️추상클래스

  • 추상 클래스는 클래스와는 다르게 인스턴스화를 할 수 없는 클래스에요!
  • 추상 클래스의 목적은 상속을 통해 자식 클래스에서 메서드를 제각각 구현하도록 강제를 하는 용도입니다!
  • 물론, 추상 클래스도 최소한의 기본 메서드는 정의를 할 수 있습니다.
  • 하지만, 골자는 핵심 기능의 구현은 전부 자식 클래스에게 위임을 하는 것이에요!

사용예시

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 { // 원의 넓이를 구하는 공식은 파이 X 반지름 X 반지름
    return Math.PI * this.radius * this.radius;
  }
}

class Rectangle extends Shape {
  width: number;
  height: number;

  constructor(width: number, height: number) {
    super();
    this.width = width;
    this.height = height;
  }

  getArea(): number { // 사각형의 넓이를 구하는 공식은 가로 X 세로
    return this.width * this.height;
  }
}

const circle = new Circle(5);
circle.printArea();

const rectangle = new Rectangle(4, 6);
rectangle.printArea();
  • Shape 클래스의 abstract getArea(): number; 를 주목해주세요. 이 코드가 바로 추상 함수입니다.
  • 이 추상 클래스를 상속 받은 자식 클래스들은 반드시 getArea 함수를 구현해야 합니다!

🖥️인터페이스

  • 인터페이스는 TypeScript에서 객체의 타입을 정의하는데 사용됩니다!
  • 인터페이스는 객체가 가져야 하는 속성과 메서드를 정의합니다.
  • 인터페이스를 구현한 객체는 인터페이스를 반드시 준수해야해요! 규약과 같아서 어길 수가 없습니다.
  • 이렇게 인터페이스를 사용하면 코드의 안정성을 높이고 유지 보수성을 향상시킬 수 있습니다.

추상화 vs 인터페이스

인터페이스는..

☑️ 구현부 제공 여부

  • 추상 클래스
    • 클래스의 기본 구현을 제공합니다.
  • 인터페이스
    • 객체의 구조만을 정의하고 기본 구현을 제공하지 않습니다.

☑️ 상속 메커니즘

  • 추상 클래스
    • 단일 상속만 지원합니다.
  • 인터페이스
    • 다중 상속을 지원합니다.
    • 즉, 하나의 클래스는 여러 인터페이스를 구현할 수 있어요!

☑️ 구현 메커니즘

  • 추상 클래스
    • 추상 클래스를 상속받은 자식 클래스는 반드시 추상 함수를 구현해야 합니다.
  • 인터페이스
    • 인터페이스를 구현하는 클래스는 인터페이스에 정의된 모든 메서드를 전부 구현해야 합니다.

☑️ 언제 쓰면 좋을까요?

  • 기본 구현을 제공하고 상속을 통해 확장하는데 초점을 맞추고 싶다면 → 추상 클래스
  • 객체가 완벽하게 특정 구조를 준수하도록 강제하고 싶다면 → 인터페이스

0개의 댓글