ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Typescript - 클래스 & 인터페이스
    TypeScript 2022. 9. 15. 17:00

    클래스

    - 객체는 코드로 작업을 수행하면서 사용할 수 있는 구체적인 요소들

    - 클래스는 데이터를 저장하고 메소드를 실행하기 위해 메소드를 저장하는데 사용하는 데이터 구조

    - 클래스를 사용하여 객체의 형태, 포함해야 하는 데이터, 클래스 기반으로 객체를 쉽게 만들 수 있으려면 어떤 메소드가 필요한지 정의할 수 있기 때문에 이를 클래스 내의 인스턴스라고 부른다.

        ㆍ객체는 클래스 내의 인스턴스인 것이다.

    - 이러한 클래스를 기반으로 하면 동일한 구조, 동일한 클래스를 기반으로 하는 동일한 메소드로 여러 객체를 빠르게 복제 가능
    - 이처럼 클래스는 객체의 형태, 포함해야 할 속성과 메소드를 정의하는 데 도움이 된다.

    - 따라서 클래스는 객체의 생성 속도를 높여주며 객체 리터럴 표기법을 사용하는 것에 대한 대안이다.

    - 클래스를 사용하여 동일한 구조와 메소드를 포함한 여러 개체를 쉽게 만들 수 있다.

     

    약식 간단화

    class Department {
        // private id: string;
        // private name: string;
        private employees: string[] = [];
    
        constructor(private id: string, public name: string) {
            // this.id = id;
            // this.name = n;
        }
    }

     

    - readonly : 특정 속성이 초기화되고나면 이후에는 변경 x

    - protected : private와 다른 점은 이 클래스에서뿐만 아니라 이 클래스를 확장하는 모든 클래스에서 사용 가능

     

    setter, getter

    get mostRecentReport() {
        if(this.lastReport){
            return this.lastReport;
        }
        throw new Error('No report found.');
    }
    
    set mostRecentReport(value: string){
        if(!value){
            throw new Error("Please pass in a valid value!");
        }
        this.addReport(value);
    }

     

    정적 메소드

    class Department {
        static fiscalYear = 2020;
        // private readonly id: string;     // readonly : 특정 속성이 초기화되고나면 이후에는 변경 X
        // private name: string;
        protected employees: string[] = []; // protected : private와 다른 점은 이 클래스에서뿐만 아니라 이 클래스를 확장하는 모든 클래스에서 사용가능
    
        constructor(private readonly id: string, public name: string) {
            // this.id = id;
            // this.name = n;
            console.log(Department.fiscalYear);
        }
    }

    - this는 클래스를 기반으로 생성된 인스턴스를 참조하기에 정적속성에 접근할 수 없다.

    - 정적 속성은 인스턴스에서 유효하지 않습니다. 정적 속성과 정적 메소드의 전체적인 개념은 인스턴스와 분리되어 있다.

       그래서 this 키워드를 사용하여 접근하는 건 불가능하다.

    - 클래스 내에서 정적 속성이나 메소드를 사용하고자 한다면 여기에 접근하기 위해 클래스를 이름을 써줘야한다.

     

    추상 클래스

    abstract class Department {
        abstract describe(this: Department) : void;
    }
    
    class ITDepartment extends Department {
        describe(): void {
            console.log('IT Department - ID: '+this.id);
        }
    }
    
    class AccountingDepartment extends Department {
        describe() {
            console.log('Accounting Department - ID: '+ this.id);
        }
    }

    - 추상 클래스는 일부 상위 클래스를 기반으로 하는 모든 클래스가 일부 공통 메소드 또는 속성을 공유하도록 하려는 경우 아주 유용할 수 있다.

    - 추상 속성을 사용할 수도 있지만 동시에 구체적인 값, 구체적인 구현, 기본 클래스를 제공하지 않고자 한다면 상속하는 클래스가 이를 수행해야한다.

    - 위의 Department를 인스턴스화 할 수 없다.

        ㆍ이는 기본적으로 상속되야할 클래스이다.

        ㆍ상속되는 클래스가 인스턴스화되고 구체적인 구현을 제공

     

    싱글톤 & 개인생성자

    - 싱글톤은 특정 클래스의 인스턴스를 정확히 하나만 갖도록 한다.

        ㆍ이 패턴은 정적 메소드나 속성을 사용할 수 없거나 사용하지 않고자 하는 동시에 클래스를 기반으로 여러 객체를 

            만들 수는 없지만 항상 클래스를 기반으로 정확히 하나의 객체만 가질 수 있도록 하고자 하는 경우에 유용하다.

     

    - 생성자를 private 해주고 클래스 자체에서 정적 메소드 호출

    - 정적 요소는 다른 모든 정적 속성(정적 메서드) 에 접근 가능

    class AccountingDepartment extends Department {
        private constructor(id:string, private reports: string[]) {
            super(id, 'Accounting');
            this.lastReport = reports[0];
        }
        
        static getInstance() {
            if(AccountingDepartment.instance){
                return this.instance;
            }
            this.instance = new AccountingDepartment('d2', []);
            return this.instance;
        }
    }
    
    
    const accounting = AccountingDepartment.getInstance();
    const accounting2 = AccountingDepartment.getInstance();

    - accounting, accounting2 둘다 같은 인스턴스를 갖게 된다.

     


    인터페이스

    - 인터페이스는 객체의 구조를 설명한다.

    - 구체적인 값이 아닌 구조만 있을 뿐이다.

     

    - 사용자 정의 타입과의 차이점

        ㆍ인터페이스는 객체의 구조를 설명하기 위해서만 사용

    - 인터페이스를 자주 사용하는 이유는 클래스가 인터페이스를 이해앟고 준수해야 하는 약속처럼 사용할 수 있다.

     

    class Person implements Greetable {
        
    }

    - implements: 여러 개의 인터페이스를 구현할 수 있다는 게 상속과의 차이점이다.

        ㆍ상속은 한 클래스로부터만 상속할 수 있다.

    - 인터페이스 내에 readonly 제어자도 추가 가능

        ㆍ다만 public, private 등은 지정할 수 없다.

     

    interface Named {
        readonly name: string;
    }
    
    interface Greetable extends Named {
        greet(phrase: string): void;
    }

    - 인터페이스는 왜 나눠야 할까?

        ㆍ어떤 애플리케이션 작업을 수행하면서 어떤 객체는 name을 입력하고 greed메소드는 제외하는 한편

             다른 객체에는 greet과 name을 입력하고자 한다면 이런 식으로 나눌 수 있다.

    - 인터페이스의 경우, 여러 인터페이스로부터 상속받을 수 있다는 차이가 있다.

     

    interface Named {
        readonly name: string;
        outputName?: string;
    }

    - 문자열이어야 하는지의 여부를 선택하고자 할 때 속성 이름 다음에 물음표를 추가하여 선택적 속성을 지정

    - 그러면 타입스크립트는 이 속성이 이 인터페이스를 구현하는 클래스 내에 있을 수 있지만 반드시 그렇지 않다고 인식

     

    - ts 파일을 js 파일로 컴파일하면 타입스크립트가 코드를 검사할 수 있도록 하는 역할을 수행하고 나면 인터페이스에 대해 아무것도 생략되지 않는다. 그저 버려질 뿐이다.

    - 그럼에도 인터페이스는 클래스나 객체가 특정 구조를 갖추도록 하고, 객체의 형태에 대한 개념을 명확하게 설명하는 강력한 기능이다.

     

    - 타입스크립트 초기에는 사용자 정의 타입을 인터페이스처럼 구현하거나 사용할 수 없었기 때문이다.

      유연성이 향상되긴 했지만 객체를 사용하여 작업을 수행하고 구조를 설명하고자 한다면

      인터페이스를 사용하는 것을 권장한다.

    'TypeScript' 카테고리의 다른 글

    Typescript - Decorators  (0) 2022.09.20
    Typescript - 고급타입  (0) 2022.09.16
    Typescript - 컴파일러( 및 구성 )  (0) 2022.09.14
    Typescript - 시작  (0) 2022.09.13

    댓글

Designed by Tistory.