추상클래스와 제네릭 (실습)

2024. 12. 29. 14:49·Backend/TypeScript

요구사항에 맞게 코드를 작성하는 과제입니다.

 


1. 클래스 구조

- PublicOfficer: 추상 클래스로, 공무원의 기본 속성과 메서드를 정의
- 하위 클래스: Police, Firefighter, Doctor가 상속

 


2. 핵심 static 클래스들

- CentralArchives: 모든 공무원 정보를 중앙 저장소에서 관리
- TrainingCenter: 공무원 객체 생성을 담당하는 팩토리 클래스 (제네릭 활용)
- Extractor: 특정 타입의 공무원 목록을 필터링하는 유틸리티 클래스

 


3. 주요 기능

- 공무원 등록/제거 (CentralArchives)
- 타입별 공무원 목록 조회 (Extractor)
- 근속연수(짝수/홀수)별 필터링 기능
- 제네릭을 활용한 타입 안전성 보장


// 1. PublicOfficer 를 상속 받는 클래스를 추가하세요. (Police, Firefighter 외 1개)
// - 속성을 추가하여도 무방합니다.
// 2. CentralArchives 클래스를 static 으로 구현하세요.
// - PublicOfficer[] 를 가지고 있는 중앙 저장소입니다.
// - 해당 필드는 외부에서는 읽기만 가능해야 합니다.
// - register, remove 메소드 구현
// - PublicOfficer[] 에 추가, 삭제합니다.
// - 모든 생성되는 Officer 는 CentralArchives 에 등록되어야 합니다.
// 3. TrainingCenter 클래스를 static 으로 구현하세요.
// - PublicOfficer 를 상속받은 클래스를 생성하는 팩토리 클래스입니다.
// - Police 뿐만 아니라 다른 Class 에 대한 train 함수도 구현해야 합니다.
// 4. Extractor 클래스를 static 으로 구현하세요.
// - CentralArchives 에서 필요한 직업의 정보를 추출하는 Utility 클래스입니다.
// - getPoliceList 메소드 구현합니다. (다른 class getList 메소드도 구현해야 합니다.)

// **추가 요구 사항**
// 5. 짝수/홀수 근속연수에 따라 Officer들을 반환해주세요.
// 6. TrainingCenter와 Extractor의 중복되는 메소드를 제네릭을 활용해서 리팩토링하세요.

abstract class PublicOfficer {
  public name: string;
  public yearsOfService: number;

  constructor(name: string, yearsOfService: number) {
    // 초기화
    this.name = name;
    this.yearsOfService = yearsOfService;
  }

  public abstract introduce(): void;

  public toString(): string {
    return `Name: ${this.name}, 
                Years of service: ${this.yearsOfService}`;
  }
}

class Police extends PublicOfficer {
  public introduce(): void {
    // 필요한 구현
    console.log(super.toString());
  }
}

class Firefighter extends PublicOfficer {
  public introduce(): void {
    // 필요한 구현
    console.log(super.toString());
  }
}

class Doctor extends PublicOfficer {
  public introduce(): void {
    // 필요한 구현
    console.log(super.toString());
  }
}

class CentralArchives {
  private static officers: PublicOfficer[] = [];
  private constructor() {}

  public static get allOfficers(): ReadonlyArray<PublicOfficer> {
    // officers 반환
    return this.officers as ReadonlyArray<PublicOfficer>;
  }

  public static register(officer: PublicOfficer): void {
    // officer 추가
    this.officers.push(officer);
  }

  public static remove(officer: PublicOfficer): void {
    // officer 제거
    const index = this.officers.indexOf(officer);
    if (index > -1) {
      this.officers.splice(index, 1);
    }
  }
}

class TrainingCenter {
  private constructor() {}

  public static train<T extends PublicOfficer>(
    constructor: new (name: string, yearsOfService: number) => T,
    name: string,
    yearsOfService: number
  ) {
    const officer = new constructor(name, yearsOfService);
    CentralArchives.register(officer);
    return officer;
  }
}

type Constructor<T> = new (...args: any[]) => T;

class Extractor {
  private constructor() {}

  public static getPoliceList(): Police[] {
    return this.filterByType(Police);
  }

  public static getFirefighterList(): Firefighter[] {
    return this.filterByType(Firefighter);
  }

  public static getDoctorList(): Doctor[] {
    return this.filterByType(Doctor);
  }

  private static filterByType<T extends PublicOfficer>(
    type: Constructor<T>
  ): T[] {
    // 어떤 인자를 받든 T 타입의 인스턴스를 만들 수 있는 생성자
    return CentralArchives.allOfficers.filter(
      (officer): officer is T => officer instanceof type
    ); // 이 조건문이 true를 반환하면 officer는 T 타입이다
  }

  // 짝수/홀수 근속연수 조회
  public static filterByYearsOfService<T extends PublicOfficer>(
    type: Constructor<T>,
    isEven: boolean
  ): T[] {
    return this.filterByType(type).filter((officer) =>
      isEven
        ? this.isEvenYearsOfService(officer)
        : !this.isEvenYearsOfService(officer)
    );
  }

  public static isEvenYearsOfService(officer: PublicOfficer): boolean {
    return officer.yearsOfService % 2 === 0;
  }

  // police
  public static getPoliceEvenYearsOfService(): Police[] {
    return this.filterByYearsOfService(Police, true);
  }

  public static getPoliceOddYearsOfService(): Police[] {
    return this.filterByYearsOfService(Police, false);
  }

  // firefighter
  public static getFirefighterEvenYearsOfService(): Firefighter[] {
    return this.filterByYearsOfService(Firefighter, true);
  }

  public static getFirefighterOddYearsOfService(): Firefighter[] {
    return this.filterByYearsOfService(Firefighter, false);
  }

  // doctor
  public static getDoctorEvenYearsOfService(): Doctor[] {
    return this.filterByYearsOfService(Doctor, true);
  }

  public static getDoctorOddYearsOfService(): Doctor[] {
    return this.filterByYearsOfService(Doctor, false);
  }
}
'Backend/TypeScript' 카테고리의 다른 글
  • JavaScript에서 Class가 결국 함수라는 게 어떤 의미일까?
  • 아이템13. type과 interface 차이점 알기
  • Interface (인터페이스)
  • Iteration Protocol (+Symbol)
kimdozzi
kimdozzi
끝까지 포기하지 않으면, 내가 다 이겨!
  • kimdozzi
    도브로
    kimdozzi
  • 전체
    오늘
    어제
    • 분류 전체보기 (132)
      • Problem Solving (49)
        • Baekjoon (29)
        • Programmers (0)
        • LeetCode (17)
        • 삼성 유형 (2)
      • Computer Science (27)
        • Operating System (2)
        • Algorithms (13)
        • Network (6)
        • DataBase (6)
      • Backend (33)
        • JavaScript (0)
        • TypeScript (6)
        • Java (7)
        • Spring Boot (7)
        • Spring Security (6)
        • JPA (2)
        • Mybatis (1)
        • Junit5 (1)
        • Redis (3)
      • DevOps (14)
        • Git, Github (5)
        • docker (4)
        • AWS (3)
        • nginx (2)
      • etc (6)
        • IntelliJ (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 티스토리
    • 설정
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    도커
    AWS
    docker
    Bucket
    온라인 쿼리
    인덱서블 타입
    docker image
    구간합
    PrefixSum
    imos법
    오블완
    누적합
    S3
    interface
    티스토리챌린지
    python
    CORS
    삼성기출
    컨테이너
    인터페이스
    오프라인 쿼리
    segment tree
    점 업데이트
    구간 업데이트
    알고리즘
    파이썬
    백준
    세그먼트 트리
    TypeScript
    인덱스 시그니처
    타입스크립트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
kimdozzi
추상클래스와 제네릭 (실습)
상단으로

티스토리툴바