TypeScript

[TypeScript] Polymorphism

winter17 2023. 8. 8. 11:35

▶ Polymorphism

  • 한 가지 타입이 다양한 형태로 동작할 수 있는 능력 → 코드의 재사용성과 유연성을 높이는 데 도움
  • 오버로딩(Overloading): 같은 이름의 함수나 메서드를 다른 매개변수 조합으로 여러 번 정의하는 것을 의미. 함수가 다양한 데이터 타입을 처리할 수 있도록 도움
  • 제네릭(Generics): 타입을 일반화하여 여러 다른 데이터 타입에 대해 동작하도록 하는 기능. 클래스, 함수, 인터페이스에서 사용할 수 있으며, 컴파일 시점에 타입을 확정하여 안정적인 코드를 작성할 수 있다
  • 상속(Inheritance): 클래스 간의 계층 구조를 만들어 상위 클래스의 속성과 메서드를 하위 클래스에서 상속받아 사용하는 것. 하위 클래스는 상위 클래스의 동작을 그대로 가져다 쓸 수 있다
  • 인터페이스(Interfaces): 다형성을 강력하게 지원하는 요소 중 하나로, 클래스나 객체가 특정한 속성과 메서드를 가지도록 정의한다. 클래스들이 같은 인터페이스를 구현함으로써 일관된 동작을 보장할 수 있다.
// 2. 인터페이스는 제네릭을 사용한다
// 제네릭은 타입을 유연하게 제공한다
interface SStorage<T>{ // storage는 이미 정의되어 있어 여기서 storage를 선언하면 오버라이딩 발생
    // [key: string]형태를 인덱스 시그니처라고 부르고, 동적으로 프로퍼티를 추가할 수 있는 객체를 정의할 때 사용됨
    [key: string]: T // 키는 문자열, 값은 제네릭 T 타입
}
// 1. <T>제네릭을 클래스로 보내고, 클래스는 제네릭을 인터페이스로 보낸 뒤에
class LocalStorage<T>{
    // private 멤버변수 storage는 SStorage타입으로 선언되고, 키-값 쌍을 담기 위한 객체이다
    // 제네릭 T에 따라서 다양한 타입의 데이터를 저장할 수 있다
    private storage: SStorage<T> = {}

    // set메서드는 키와 값을 받아서 storage객체에 저장한다.
    // 여기서 제네릭 T는 value타입을 결정한다
    set(key: string, value: T){
        this.storage[key] = value
    }

    // remove 메서드는 주어진 키를 사용하여 storage 객체에서 해당 키의 값을 제거한다
    remove(key: string){
        delete this.storage[key]
    }

    // get 메서드는 주어진 키를 사용하여 stroage 객체에서 해당 키의 값을 가져온다
    // 반환 타입인 T는 해당 키에 저장된 값의 타입을 의미한다.
    get(key: string):T{
        return this.storage[key]
    }

    // clear 메서드는 stroage 객체를 빈 객체로 초기화하여 모든 데이터를 삭제한다
    clear(){
        this.storage = {}
    }
}
// 제네릭 T를 문자열로 지정하여 stringsStorage 인스턴스 생성
const stringsStorage = new LocalStorage<string>
// 문자열 'xxx'에 해당하는 값을 가져온다
stringsStorage.get('xxx')
// 'hello' 키에 'how are you' 값을 저장한다
stringsStorage.set('hello', 'how are you')

// 제네릭 T를 불리언으로 지정하여 booleansStroage 인스턴스 생성
const booleansStroage = new LocalStorage<boolean>()
// 'yyy' 키에 해당하는 값을 가져온다
booleansStroage.get('yyy')
// 'hello' 키에 true 값을 저장한다.
booleansStroage.set('hello', true)

 

◎ LocalStorage API using abstract classes and generics

interface SStorage<T>{
    [key: string]: T
}

abstract class AbstractStorage<T>{
    public storage: SStorage<T> = {}

    abstract setItem(key: string, value: T): void
    abstract getItem(key: string): T | undefined
    abstract clearItem(key: string): void
    clear(): void {
        this.storage = {}
    }
}

class LocalStorage<T> extends AbstractStorage<T>{
    setItem(key: string, value: T){
        this.storage[key] = value
    }
    getItem(key: string): T | undefined{
        return this.storage[key]
    }
    clearItem(key: string){
        delete this.storage[key]
    }
}

https://developer.mozilla.org/en-US/docs/Web/API/Storage

 

 

◎ Geolocation API using overloading

interface GeoSuccess{
    coords: Coordinates;
}

interface GeoError{
    timeout?: number;
}

interface Coordinates {
  latitude: number;
  longitude: number;
  accuracy: number;
}

interface Options {
  timeout?: number;
  maximumAge?: number;
  enableHighAccuracy?: boolean;
}

class MiniGeoLocation{
// () 안의 내용은 함수 매개변수와 타입
// {} 안의 코드는 함수가 호출될 때 실제로 실행되는 코드
    getCurrentPosition(
        // getCurrentPosition 메서드의 시그니처에서 success는 함수 매개변수
        // success 함수는 GeoSuccess타입의 매개변수 position을 받는다.
        // 이 함수의 반환 값은 없다
        success: (position: GeoSuccess) => void,
        error?: PositionErrorCallback | undefined,
        options?:Options,
    ): void{
        navigator.geolocation.getCurrentPosition(success, error, options)
    }
    clearWatch(id: number){
        navigator.geolocation.clearWatch(id)
    }
    watchPosition(
        success: (position: GeoSuccess) => void,
        error?: PositionErrorCallback | undefined,
        options?:Options,
    ): void{
        navigator.geolocation.watchPosition(success, error, options)
    }
}
// type PositionErrorCallback = (error: PositionError) => void;

 

https://developer.mozilla.org/en-US/docs/Web/API/Geolocation