Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- oracle
- Git
- 리눅스
- 오류해결
- 자바스크립트
- 개발
- 도쿄
- GitHub
- 1박2일
- error
- 개발자
- JavaScript
- 별5개
- 3박4일
- 안드로이드
- Eclipse
- 깃허브
- AndroidStudio
- 재밌당
- db
- android studio
- 자바
- 공부
- Android
- Java
- 코틀린
- kotlin
- 친구랑
- 안드로이드스튜디오
- 오라클
Archives
- Today
- Total
dev_eunz
[타입스크립트] 클래스와 인터페이스 본문
728x90
반응형
클래스와 인터페이스
C#과 타입스크립트의 클래스의 기능 유사
- 클래스와 상속
- 타입지정타입 안정성을 어느정도 확보 가능지정한 값 이외의 값을 사용하면 컴파일 에러 발생
- type Color = 'Black' | 'White' type File = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' type Rank = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
- Color / File / Rank 라는 변수에 값을 제한할 수 있음
- 접근 한정자
- public
- 어디에서나 접근 가능
- private자동으로 매개변수를 this에 할당
- 서브클래스 인스턴스에는 접근 불허
- 접근 한정자
- protected서브클래스 인스턴스 모두에 접근 허용
- private처럼 프로퍼티를 this에 할당
- readonlykotlin으로 치면, val / java로 치면 final
- 초기 값 할당 후, 더 이상 값을 덮어쓸 수 없음
- 이를 통해 내부 구현 정보를 너무 공개하지 않고, 잘 정의된 API만 노출하도록 클래스 설계 가능
- abstract아래와 같이 직접 인스턴스화 하려고 하면 에러 발생 ( 추상 클래스의 인스턴스 생성 불가 )필요한 메서드를 추상 클래스에 자유롭게 추가 가능이와 같이 bbb 메서드 추가했을 때,추상 클래스를 구현할 때는, 반드시 추상 메서드도 구현해야 함
- Test를 상속받은 클래스가 bbb 메서드를 구현하지 않으면 컴파일 타임에 에러 발생
- abstract class Test { aaa(testType: TestType) { this.testType = testType } abstract bbb(testType: TestType): boolean }
- new Piece('White', 'E', 1) // Error
- 상속받은 클래스를 통해서만 인스턴스화 할 수 있도록 허용
- 클래스
- 구체 클래스
- 추상 클래스
- 추상 메서드, 추상 프로퍼티 가질 수 있음
- 인스턴스 프로퍼티도 가질 수 있음private / protected / public 중 한 가지 한정자 가질 수 있음
- readonly 추가할 수 있음
- 기본값: public
- 메서드private / protected / public 중 한 가지 한정자 가질 수 있음
- 인스턴스 메서드
- 정적 메서드
- 기본값: public
- super메서드에만 접근가능, 프로퍼티 접근 불가능
- super.methodName
- super() : 생성자 함수에서만 호출할 수 있음
- 자식 클래스가 부모 클래스에 정의된 메서드를 오버라이드 하면, 자식 인스턴스는 super를 통해 부모 버전의 메서드를 호출 가능
- this를 반환 타입으로 사용
- Set 이라는 클래스 생성
class Set { has(value: number): boolean { ... } add(value: number): Set { ... } }
- Set 을 상속받는 클래스 생성
⇒ 상속받는 서브클래스는 this를 반환하는 모든 메서드의 시그니처를 오버라이드 해야함class MutableSet extends Set { delete(value: number): boolean { ... } add(value: number): MutableSet { ... } }
this를 통해서 MutableSet 클래스 생성시에도 add 메서드를 오버라이드 할 필요가 없어짐class Set { has(value: number): boolean { ... } add(value: number): this { ... } }
- 이럴 때, this를 사용
- 인터페이스타입별칭 ( type ) 과 유사이와 동일한 인터페이스Meat 타입별칭을 사용한 모든 곳에 인터페이스 대신 사용 가능
인터페이스로 하면,※ 인터페이스는 객체타입, 클래스, 다른 인터페이스 모두를 상속받을 수 있음type Food = { calories: number tasty: boolean } type Meat = Food & { salty: boolean } type Cookie = Food & { sweet: boolean }
- 타입별칭의 경우, 타입 연산자를 포함한 모든 타입이 등장
- 아래와 같은 경우, 인터페이스로 재작성 불가
type A = number type B = A | string
- 인터페이스를 상속할 때, 상속받는 인터페이스 타입에 상위 인터페이스를 할당할 수 있는지 확인
아래와 같은 경우, bad 메서드에 A에서는 number를 사용하였기에 B에 있는 string 타입에 할당할 수 없음( 코드 편집기로 확인 가능 )interface A { good(x: number): string bad(x: number): string } interface B extends A { good(x: string | number): string bad(x: string): string }
- 이름과 범위가 같은 인터페이스가 여러개 있다면 이들이 자동으로 합쳐짐⇒ 선언 합침
- 선언 합침
위와같이 두 개의 인터페이스를 선언하면, 아래와 같이 자동으로 합쳐짐그래서 아래와 같이 사용할 수 있게 됨이를 타입별칭으로 사용하면, 오류가 나게 됨interface User { name: string } interface User { age: number }
제네릭을 선언한 인터페이스의 경우, 제네릭들의 선언 방법과 이름까지 똑같아야 합칠 수 있음interface User { age: string } interface User { age: number }
interface User<Age extends number> { age: Age } interface User<Age extends string> { age: Age }
- 아래와 같이 제네릭 타입이 다르다면, 오류 발생
- 인터페이스에서 오류가 나는 경우
- let a: User = { name: 'Eunji', age: 19 }
- interface User { name: string age: number }
- 같은 이름으로 정의된 여러 정의를 자동으로 합침
- 선언 합침
- 같은 조건에서 타입 별칭이 여러개라면, 컴파일 에러가 남
- 예시Cat은 Animal이 선언하는 모든 메서드를 구현해야 함
- 필요하다면 메서드나 프로퍼티 추가 구현 가능
- interface Animal { eat(food: string): void sleep(hours: number): void } class Cat implements Animal { eat(food: string) { console.info('Ate some', food, '. Mmm!') } sleep(hours: number) { console.info('Slept for', hours, 'hours') } }
- 예시
- interface Animal { readonly name: string eat(food: string): void sleep(hours: number): void } interface Feline { meow(): void } class Cat implements Animal, Feline { name = 'Whiskers' eat(food: string) { console.info('Ate some', food, '.Mmm!') } sleep(hours: number) { console.info('Slept for', hours, 'hours') } meow() { console.info('Meow') } }
- 객체 타입처럼 인스턴스 프로퍼티(지역변수)를 readonly로 설정 가능
- 오버로드한 메서드가 작성됨
- interface Food { calories: number tastuy: boolean } interface Meat extends Food { salty: boolean } interface Cookie extends Food { sweet: boolean }
- 타입 조합
- interface Meat { calories: number salty: boolean tasty: boolean }
- type Meat = { calories: number salty: boolean tasty: boolean }
- 타입에 이름을 지어주는 수단
- 인터페이스 구현 vs 추상 클래스 상속인터페이스가 더 범용으로 쓰임
- 인터페이스객체, 배열, 함수, 클래스, 클래스 인스턴스를 정의할 수 있음
- 컴파일 타임에만 존재
- 형태를 정의하는 수단
- 추상 클래스런 타임의 자바스크립트 클래스 코드 만듬
- 인터페이스와 차별점프로퍼티와 메서드에 접근 한정자 지정 가능
- 생성자와 기본 구현을 가질 수 있음
- 오직 클래스만 정의 가능
- 추상 클래스는 특별한 목적과 풍부한 기능을 가짐
- 둘은 아주 비슷
- 타입스크립트는 클래스 비교시 구조 기준으로 비교 ★ ( 타 언어와 차이점 )
- 예시
- class Zebra { trot() { ... } } class Poodle { trot() { ... } } function ambleAround(animal: Zebra) { animal.trot() } let zebra = new Zebra let poodle = new Poodle ambleAround(zebra) ambleAround(poodle) // OK. 에러 없음
- 예시{x: 1} 은 private가 아니기 때문에 할당할 수 없음
- class A { private x = 1 } class B extends A {} function f(a: A) {} f(new A) // OK f(new B) // OK f({x: 1}) // ERROR
- 클래스는 값과 타입을 모두 선언타입 추론 기능 덕분에 컴패니언 타입 같은 기능 구현 가능
- 타입 추론 예시
- // 값 let a = 1999 function b() {} // 타입 type a = number interface b { (): void } ... if(a + 1 > 3) // 문맥상 값 a(1999)로 추론 let x: a = 3 // 문맥상 타입 a(number)로 추론
- 타입 스크립트는 값 / 타입으로 이루어짐
- 클래스 정의 ( 5.6 ) 🤔🤔🤔
- 좀 더 살펴보기… 🤔 ★★★★
- 다형성제네릭 타입의 범위 : 클래스나 인터페이스 전체가 될 수도 있고, 특정 메서드로 한정할 수도 있음
- 예시
- class MyMap<K, V> { constructor(initialKey: K, initialKey: V) { ... } get(key: K): V { ... } set(key: K, value: V): void { ... } // 자신만의 제네릭 추가 선언 ( K1, V1 ) merge<K1, V1>(map: MyMap<K1, V1>): MyMap<K| K1, V| V1> { ... } // 정적 메서드 static 에서는 값 수준에서 접근할 수 없어 자신만의 K, V 선언 static of<K, V>(k: K, v: V): myMap<K, V> { ... } }
- 예시
- interface MyMap<K, V> { get(key: K): V set(key K, value: V): void }
- 예시
- let a = new MyMap<string, number>('k', 1) // MyMap<string, number> let b = new MyMap('k', true) // MyMap<string, boolean> a.get('k') b.set('k', false)
- 클래스와 인터페이스도 기본값, 상한/하한 설정을 포함한 다양한 제네릭 타입 매개변수 기능 지원
- 믹스인 🤔🤔🤔둘 이상의 클래스를 상속받는 다중 상속과 관련된 기능 제공상태를 가질 수 있음 ( 인스턴스 프로퍼티 )생성자를 가질 수 있음 ( 클래스가 혼합된 순서와 같은 순서로 호출 )
- 구체 메서드만 제공 ( 추상 메서드는 안됨 )
- 역할 지향 프로그래밍(role-oriented programming)
- trait, mixing 키워드를 제공하지는 않지만, 손쉽게 구현 가능
- 데코레이터 🤔클래스, 클래스 메서드, 프로펕, 메서드 매개변수를 활용한 메타 프로그래밍에 깔끔한 문법 제공
데코레이터를 사용하지 않고, 같은 기능을 구현할 수 있음데코레이터 타입 각각에 대해 주어진 이름 범위에 존재하는 함수와 해당 데코레이터 타입에 요구되는 시그니처를 필요로 함직접 구현 / NPM으로 설치기능이 더 완벽해지기 전까지는 일반 함수 사용할 것 권장@serializable class APIPlayload { getValue(): Payload { ... } }
- 특정 시그니처를 만족하는 일반 함수
- 기본으로 제공하는 데코레이터 X
- let APIPayload = serializable(class APIPayload { getValue(): Payload { ... } })
- 장식하는 대상의 함수를 호출하는 기능 제공
- 타입스크립트의 실험적 기능
- final 클래스
- 생성자를 private로 선언하면, new로 인스턴스 생성/ 클래스 확장 불가능해짐
- 클래스를 인스턴스화 하는 기능도 사라짐
- 예시위와 같이 생성자를 private로 선언했다고 하면,생성자가 private이기에 클래스를 확장할 수 없음생성자가 private 이므로 클래스 내부 선언에서만 접근 가능
- new MessageQueue([]) // ERROR
- class BadQueue extends MessageQueue { } // ERROR
- class MessageQueue { private constructor(private message: string[]) { } }
- final 클래스처럼 상속만 막고, 인스턴스는 정상적으로 만들 수 있게 하는 방법
- 예시이렇게 구현을 하면, 인스턴스 생성은 가능
MessageQueue.create([])
- class BadQueue extends MessageQueue { } // Error
- class MessageQueue { private constructor(private message: string[]) { } static create(message: string[]) { return new MessageQueue(message) } }
- 비공개 생성자(private constructor)로 흉내낼 수 있음
- 디자인 패턴
728x90
반응형
'IT' 카테고리의 다른 글
[Java] BigDecimal 데이터 비교하기 (0) | 2022.09.06 |
---|---|
[JAVA] javax.crypto.BadPaddingException 암복호화 키 오류 해결 (0) | 2022.08.21 |
[ORACLE] ORA-00932: 일관성 오류 해결 (0) | 2022.08.21 |
[Mac] 맥OS에 Node.js 설치하기 (0) | 2022.08.17 |
[TypeScript] 타입스크립트의 Constructor 메서드 (0) | 2022.08.13 |
Comments