본문 바로가기

프로그래밍/TypeScript

07. 클래스와 인터페이스


7.2 인터페이스

인터페이스는 자바스크립트(ES6)에서는 지원하지 않습니다.
인터페이스는 타입이며 컴파일 후에는 사라집니다.
추상클래스는 선언과 구현이 모두 존재하지만, 인터페이스는 선언만 존재합니다.

멤버 변수와 함수를 선언할 수 있지만, 접근제한자는 설정할 수 없습니다.
자식 인터페이스는 여러 부모 인터페이스를 다중상속할 수 있습니다.

7.2.2 인터페이스의 역할과 컴파일 결과 분석

자바스크립트 객체는 구조를 고정할 수 없고 쉽게 변화하는 특성이 있습니다.
객체는 유지보수와 확장, 안정성을 고려해 선언과 동시에 고정할 필요가 있습니다.

인터페이스를 이용하면 객체의 구조를 고정할 수 있습니다.
인터페이스는 컴파일 과정에서 타입 검사의 용도로 사용되고, 컴파일 후에는 제거됩니다. 


P.208 
인터페이스 사용시

-----------------------------------------
interface ICar { name: string; }
class MyCar { }

let mCar: ICar = { name: "car" };
console.log(typeof mCar);
console.log(typeof MyCar);
// console.log(typeof ICar); // 유효하지 않음
------------------------------------------

- ES6로 컴파일 할 경우
------------------------------------------
class MyCar {
}
let mCar = { name: "car" };
console.log(typeof mCar);
console.log(typeof MyCar);
------------------------------------------
: 인터페이스는 타입 검사 용도가 끝나면 사라지고 ES6에서 지원하는 클래스 선언만 납는다.

- ES5로 컴파일 할 경우
------------------------------------------
var MyCar = /** @class */ (function () {
    function MyCar() {
    }
    return MyCar;
}());
var mCar = { name: "car" };
console.log(typeof mCar);
console.log(typeof MyCar);
------------------------------------------
: ES5는 클래스를 지원하지 않기때문에 즉시 실행함수로 변환된다. 

7.2.3 클래스를 배열 요소 타입으로 지정함

1. 객체 리터럴
클래스는 객체 리터럴의 타입으로 사용할 수 있습니다. 
배열의 요소가 객체 리터럴이면 배열 타입을 선언할 때 
배열 요소의 타입을 객체 리터럴로 지정해 타입 안전성을 강화할 수 있습니다. 

var person2: { name: string, city: string }[];

2. 클래스 배열
------------------------------------------
class Person3 {
    public full: string;
    constructor(public name: string, public city: string) {
        this.full = name + "(" + city + ")";
    }
}
let person3: Person3[] = [
    new Person3("kim", "seoul"),
    new Person3("Lee", "busan"),
    new Person3("Park", "Ui"),
];
console.log(JSON.stringify(person3));
------------------------------------------

7.2.4 인터페이스 배열
위에 클래스와 마찬가지로 인터페이스도 객체 리터럴과 클래스 배열로 나타낼 수 있습니다.  
다만 인터페이스는 타입 선언이 많아도 컴파일(ES6) 후에는 모두 사라지므로
런타임 성능에 영향을 미치지 않습니다. 

7.2.5 인터페이스에 함수 타입을 정의

인터페이스는 익명함수에 대한 함수타입을 정의할 수 있는 기능도 있습니다.

------------------------------------------
interface IFormat {
    (data: string, toUpper?: boolean): string;
}
let format: IFormat = function (str: string, isUpper: boolean) {
    if (isUpper) {
        return str.toUpperCase();
    } else {
        return str.toLowerCase();
    }
};
------------------------------------------

이렇게 선언한 인터페이스는 익명 함수를 할당받는 변수의 타입으로 선언할 수 있습니다. 
format 변수는 익명 함수를 할당받고 있으며
익명 함수의 타입으로 인터페이스 IFormat을 선언했습니다. 
이때 함수 타입의 매개변수 이름은 정확히 일치하지 않아도 됩니다. 


7.3.1 오버라이딩 메소드 재정의 하기

Overridden method, Overridding method

조건1) 오버라이든 메서드의 매개변수 타입은 오버라이딩 메서드의 매개변수 타입과 같거나 상위 타입이어야 한다.
(단, 오버라이딩 메소드의 매개변수 타입이 Any 타입인 경우는 제외한다.)

조건2) 오버라이든 메서드의 매개변수 개수가 오버라이딩 메서드의 매개변수 개수와 같거나 많아야 한다. 
(단, 조건1이 성립된다는 전제가 있어야 함)

오버라이딩이 가능한 조건.

1) 오버라이든 메서드의 매개변수 타입이 
오버라이딩 메서드의 매개변수보다 상위타입이면 가능하다. 
 
flight(kmDistance: any = 0); // 오버라이든 메서드
flight(kmDistance2: number = 0);// 오버라이딩 메서드

2) 오버라이딩 메서드의 매개변수(kmDistance2)가 Any 타입이면 어떤 타입이든 받을 수 있다. 

flight(kmDistance: any = 0); // 오버라이든 메서드
flight(kmDistance2: any = 0); // 오버라이딩 메서드

3) 오버라이드 메서드의 매개변수 개수가 오버라이딩 메서드의 매개변수와 같거나 많으면
오버라이딩이 가능하다.

flight(kmDistance: number = 0, kmSpeed: number = 0); // 오버라이든 메서드
flight(kmDistance2: number = 0); // 오버라이딩 메서드

*) 매개변수 개수는 같지만 조건1과 조건2가 동시에 성립하지 않으면
오버라이딩이 되지 않는다. 

flight(kmDistance: number = 0, kmSpeed: number = 0); // 오버라이든 메서드
flight(kmDistance2: number = 0, kmSpeed: string); // 오버라이딩 메서드


- 오버라이딩 메서드를 오버로딩하기 

typeCheck(value: any): void 으로 오버라이딩 메서드를 만들고 오버로드 메소드에
typeCheck(value: string): void 같은 타입의 메소드를 포함해야한다.

typeCheck(value: number): void;
typeCheck(value: string): void;
typeCheck(value: any): void {...}


- 인터페이스를 클래스에서 오버로딩하기

------------------------------------------
interface IPoint {
    getX(x: any): any;
}
class Point implements IPoint {
    getX(x?: number | string): any {
        if (typeof x === "number") {
            return x;
        } else if (typeof x === "string") {
            return x;
        }
    }
}
let p = new Point();
console.log(p.getX());
console.log(p.getX("hello"));
console.log(p.getX(123));
------------------------------------------

getX 메소드는 매개변수 x를 선언하고 ?를 추가해
선택매개변수가 되어 입력값이 없는 호출을 받을 수 있도록 했습니다.

인터페이스를 이용하면 선언과 구현을 분리하고 구현부의 구조를 강제할 수 있습니다.
이 점에서는 로직과 구조가 섞여있는 클래스를 상속해 오버로딩하는 것보다
구조만을 포함하고 있는 인터페이스를 사용하는 것이 복잡도가 낮습니다. 

'프로그래밍 > TypeScript' 카테고리의 다른 글

08.모듈  (0) 2019.10.16
07.클래스와 인터페이스 기반의 다형성  (0) 2019.10.15
06. 함수  (0) 2019.10.15
04. 조건문, 제어문 / 05. 연산자  (0) 2019.10.15
03. 변수  (0) 2019.10.15