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