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

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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바