본문 바로가기
TIL

TIL #20) 객체 지향 프로그램

by 해룸 2024. 2. 19.

Today I Learned

상속

상속은 객체 지향 프로그래밍에서 클래스 간의 관계를 정의하는 중요한 개념.

상속을 통해 기존 클래스의 속성과 메서드를 물려받아 새로운 클래스를 정의할수있고, 똑같은 코드를 계속 반복할 필요가 없다. 상속을 구현하려면 extends 키워드를 사용하면 가능~!

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 함수의 동작을 새롭게 정의한다. 이걸 오버라이딩이라 한다!

 

서브타입, 슈퍼타입

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

서브타입(자식클래스)가 들어가는곳에는 슈퍼타입(부모클래스)가 안전하게 치환 가능하다!(upcasting)

타입변환은 암시적으로 이뤄져 별도의 타입변환구문이 필요없음

 

let animal: Animal;
animal = new Dog('또순이');

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

슈퍼타입이 들어가는곳에 서브타입을 쓰려면 as키워드로 명시적 타입변환을 해줘야한다.(downcasting)

 

추상클래스

추상클래스는 클래스와는 다르게 인스턴스화를 할 수 없는 클래스!

상속을 통해 자식클래스에서 메서드를 제각각 구현하도록 강제하는 목적임. 그러나 핵심기능은 전부 자식클래스에 위임하도록 한다.

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 { // 원의 넓이를 구하는 공식은 파이 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();

이 추상클래스를 상속받은 자식클래스들은 반드시 getArea 함수를 구현해야함!!(추상함수구현!!)

 

인터페이스

TypeScript에서 객체의 타입을 정의하는데 사용한다. 객체가 가져야하는 속성과 메서드를 정의한다.

인터페이스를 구현한 객체는 반드시 인터페이스를 준수해야함. 규약!! 이라고 생각하기

코드의 안정성을 높이고 유지보수성을 향상시킬수있다. 주로 추상클래스보다는 인터페이스를 많이 쓴다 함.

 

추상클래스와 인터페이스의 차이?

'TIL' 카테고리의 다른 글

TIL #22) test code - 의존성 주입하기  (0) 2024.02.22
TIL #21) 기존코드 3계층 분리하기  (0) 2024.02.21
TIL #19) 객체 지향 설계 5원칙(SOLID)  (0) 2024.02.16
TIL #18) Transaction  (0) 2024.01.30
TIL #17) ORM, Prisma 파먹기  (0) 2024.01.27