TypeScript

객체 지향 프로그래밍

차돌박이츄베릅 2023. 7. 27. 08:14

클래스 정의하기

  • 생성자(constructor)는 클래스의 인스턴스를 생성하고 초기화할때 최초로 불리는 메서드.
    그 이후로는 불리지 않음. 객체를 만드는 그 시점에 한번만 불리는 메서드
  • 보통, 생성자로 객체 속성을 초기화 하는것 뿐 아니라 객체가 생성이 될 떄 꼭 되어야 하는 초기화 로직을 집어넣기도 함
    예를 들어, DBConnector라는 클래스가 있다면 이 클래스 타입의 객체가 생성이 될 때 생성자에서 DB 연결을 미리 ㄱ
// TypeScript에서 클래스를 정의하려면 class 키워드를 사용하면 됩니다!
class Person {
  // 속성 정의
  name: string;
  age: number;
  
  // 생성자
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

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

// new 키워드를 사용하여 객체를 생성할 수 있어요.
const person = new Person('Spartan', 30);
person.sayHello();

 

클래스 접근 제한자(타입 스크립트)

  • public: 클래스 외부에서도 접근 가능. 기본 설정. 민감하지 않은 객체 정보 열람할 때
  • private: 보통 클래스 속성은 대부분 private로 접근 제한자를 설정해줌⭐
    외부에서 직접적으로 객체의 속성을 변경할 수 없음.
    속성을 보거나 편집하려면 getter/setter메서드를 별도로 준비해놔야 함
  • protected: 클래스 내부 && 상속 받은 자식 클래스까지도 접근 가능
class Person {
  private name: string;
  private age: number;

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

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

 

 


상속(inheritance)

 

기존 클래스의 속성과 메서드를 물려받아 새로운 클래스를 정의

class Animal {
  name: string;

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

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

// 여기서 Animal을 부모 클래스, Dog를 자식 클래스!
class Dog extends Animal {
  age: number;

  constructor(name: string) {
    // super 키워드는 자식 클래스에서 생성자를 정의할 때 부모 클래스의 생성자를 호출해야 하는데 쓰임
    super(name);
    this.age = 5;
  }

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

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

// 상속을 구현하려면 extends 키워드를 사용하면 됩니다!
class Cat extends Animal { // Animal과 다를게 하나도 없어요!
}

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

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

 

서브타입, 슈퍼타입

upcast과 downcast는  슈퍼타입과 서브타입으로 변환할 수 있는 타입 변환 기술

 

upcast: subtype(string) -> supertype(any, unknown)
사용 예) 예를 들어, Dog, Cat, Lion 그리고 기타 등등 다양한 동물을 인자로 받을 수 있는 함수를 만들고 싶다면? -> Animal 타입의 객체를 받으면 모두 다 받을 수 있다!

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

// upcasting의 경우, 타입 변환은 암시적으로 이루어져 별도의 타입 변환 구문이 필요가 없어요!
// 단지 슈퍼타입 변수에 대입만 했을 뿐
let animal: Animal = dog; // upcasting 발동! 

animal.eat(); // 에러. 슈퍼타입(Animal)으로 변환이 되어 eat 메서드를 호출할 수 없어요!

 

downcast: supertype(any, unknown) -> subtype(string)

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

// as 키워드로 명시적으로 타입 변환을 해줘야 함
let realDog: Dog = animal as Dog;

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

 

Animal은 Dog, Cat의 슈퍼타입,
Dog, Cat은 Animal의 서브타입?

 

 


추상 클래스

  • 클래스와는 다르게 인스턴스화를 할 수 없는 클래스
  • 상속을 통해 자식 클래스에서 메서드를 제각각 구현하도록 강제를 하는 용도
  • 추상 클래스도 최소한의 기본 메서드는 정의를 할 수 있으나, 핵심 기능의 구현은 전부 자식 클래스에게 위임을 하기 위함!

자식 클래스 니가 직접 구현해.
자식 클래스에서 구현 안하면 에러냄..

// 추상 클래스 및 추상 함수는 abstract 키워드를 사용하여 정의
abstract class Shape {
  // 추상 클래스는 1개 이상의 추상 함수가 있는 것이 일반적
  // 이 추상 클래스를 상속 받은 자식 클래스들은 반드시 getArea 함수를 구현해야 합니다!
  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();

 

인터페이스

  • TypeScript에서 객체의 타입을 정의하는데 사용
  • 객체가 가져야 하는 속성과 메서드를 정의.
  • 인터페이스를 구현한 객체는 인터페이스를 반드시 준수해야해요! 규약과 같아서 어길 수가 없다

 

구분 추상 클래스 인터페이스
구현부 제공 여부 클래스의 기본 구현을 제공합니다. 객체의 구조만을 정의하고 기본 구현을 제공하지 않습니다.
상속 메커니즘 단일 상속만 지원합니다. - 다중 상속을 지원합니다. 
- 즉, 하나의 클래스는 여러 인터페이스를 구현할 수 있어요!
구현 메커니즘 추상 클래스를 상속받은 자식 클래스는 반드시 추상 함수를 구현해야 합니다. 인터페이스를 구현하는 클래스는 인터페이스에 정의된 모든 메서드를 전부 구현해야 합니다.
사용 예 기본 구현을 제공하고 상속을 통해 확장하는데 초점을 맞추고 싶다면 객체가 완벽하게 특정 구조를 준수하도록 강제하고 싶다면

 

'TypeScript' 카테고리의 다른 글

[실습] 도서관 프로그램  (0) 2023.07.27
객체 지향 설계 원칙 - S.O.L.I.D  (0) 2023.07.27
[실습] 카페 주문 프로그램  (0) 2023.07.27
고급 타입  (0) 2023.07.27
기본 타입 / readonly / any와 unknown, union  (0) 2023.07.27