ABOUT ME

Today
Yesterday
Total
  • [TS] 클래스
    codeStates front-end/Typescript 2023. 3. 20. 21:26
    반응형

     

     

     

     

    📌  클래스

     

     

     

    📍클래스

     

    타입스크립트는 자바스크립트와 동일하게 클래스를 선언하고 사용할 수 있다.

    클래스란? 여러 객체들을 생성하기 위한 탬플릿 (EX) 클래스 : 붕어빵 기계, 객체 : 붕어빵)

    클래스의 핵심 기능은 상속!!!! 👉🏼👉🏼 효율적이고 유지보수가 편함

     

    빈 클래스를 생성해서 새로운 프로퍼티를 선언

     

    class Site {
      no: number = 0;
    }

     

    🔗  클래스 메서드

    클래스는 기본적으로 속성메서드를 갖는다.

    클래스에서 매게변수 타입에 타입이나 기본값을 지정하지 않으면 any

    메서드를 호출하려면 허용 가능한 수의 인수가 필요하고, 재귀함수가 아니라면 대부분 반환타입 유추 가능

     

    빈 프로퍼티 아래에 메소드를 추가

     

    class Site {
      no: number;
    
      constructor(no: number) {
        this.no = no;
      }
    
      getNo() {
        return this.no;
      }
    }

     

    🔗  클래스 속성

     

    아래 코드를 보면 name은 속성이며, draw()는 메서드를 가리킨다.

     

    class Shape {
        name: string;
     
        constructor(name: string) {
            this.name = name; // ok!
        }
        
        // 존재하지 않는 멤버의 접근하려고 시도하면 타입 오류
        this.nonName = name; //Error
     
        draw(x: number, y: number) {
            console.log("Draw " + this.name + " at " + x + "," + y);
        }
    }

     

    TS에서는 클래스의 속성을 읽거나 쓰려면 클래스에 명시적으로 선언

    클래스 속성 이름 뒤에 선택적으로 타입 에너테이션이 붙는다.

     

     

     

    🔗  함수 속성

     

    JS에서의 클래스 안에 함수 선언1

     

    // 멤버 이름 뒤에 괄호를 붙이는 메서드 접근 방식
    class WithMethod{
    	myMethod(){}
    }
    
    new WithMethod().myMethod === new WithMethod().myMethod;// true

     

    JS에서의 클래스 안에 함수 선언2

     

    // 값이 함수인 속성을 선언하는 방식
    class WithPtoperty{
    	myProperty : () => {}
    }
    
    new WithMethod().myProperty === new WithMethod().myProperty; // false

     

    함수 속성은 클래스 멤버로 할당된 값 👉🏼👉🏼 그 값은 함수

     

    (input : boolean) => string 인 속성을 갖고 있어 number속성은 바로 에러를 알려준다.

     

     

     

    🔗  초기화 검사

     

    타입스크립트는 엄격한 컴파일러 설정이 활성화되어 있는 상태

    undefined 타입으로 선언된 각 속성이 생성자에서 할당되었는지 확인

    초기화 검사는 클래스 속성에 값을 할당하지 않는 실수를 예방할 수 있어 유용하다.

     

    class WithValue{
        immediate = 0; // ok
        later : number; // ok(construtor에서 할당)
        mayBeUndefined : number | undefined; // Ok(undefined가 되는 것이 허용됨)
        unused : number; // Error
    
        constructor(){
            this.later = 1;
        }
    }

     

     

    🔗  선택적 속성

     

    클래스는 설정된 인터페이스에 정의된 속성 또는 메서드를 반드시 사용하지 않고, 필요에 따라 선택적으로 사용하고 싶을 수도 있다.

    이 경우 옵션(Optional) 속성 설정을 통해 사용자가 선택적으로 사용하게 설정

     

     

    더보기

    속성 이름 뒤에 ?를 붙이면 옵션 속성

     

    interface에서 선택적 속성을 이용해서 선언 후 클래스를 선언 해 상속시키는 예제

     

    // 공식사이트 예제
    interface ButtonInterface {
      // 속성 이름 뒤에 ? 기호가 붙으면 옵션 속성이 됩니다.
      onInit?():void;
      onClick():void;
    }
    
    class ButtonComponent implements ButtonInterface {
    
      // onInit 메서드가 설정되지 않아도 오류를 발생하지 않습니다.
      onClick() { console.log('버튼 클릭') }
    
    }

     

     

    🔗  읽기 전용 속성(readonly)

     

    말 그대로 읽기 전용을 나타내며 사용할 경우 값 변경 불가

     

    class Site {
    // readonly 사용
      readonly no: number;
      url: string;
    
      constructor(no: number, url: string) {
        this.no = no;
        this.url = url;
      }
    }
    
    const Webisfree = new Site(1, 'webisfree.com');
    
    Webisfree.no = 2;
    // 에러 발생. Readonly이므로 값 변경이 불가함

     

     

    🔗  타입으로서의 클래스

     

     

     

    타입 시스템은 클래스 자체와 타입 에너테이션에서 사용할 수 있는 타입을 모두 생성하는 부분이 특징이다.

    타입 에너테이션을 통해 할당할 수 있는 값만을 타입 스크립트에서 알려준다.

    타입스크립트는 클래스의 동일한 멤버를 모두 포함하는 객체 타입 클래스만 할당 가능하다

     

    class Teacher {
        sayHello(){
            console.log("Hello");
            }
    }
    
    let teacher : Teacher;
    teacher = new Teacher(); //ok
    teacher = "Wahoo!"; 
    // error string 형식은 할당할 수 없습니다.

     

     

     

    🔗 클래스와 인터페이스

     

    🙋🏻‍♂️ 인터페이스란? 클래스나 객체에서 사용할 프로퍼티와 메소드를 클래스 외부에 따로 분리하여 선언할 수 있는 방법

     

    타입스크립트는 클래스 이름 뒤에 implements를 사용하여 클래스나 객체에 사용

    아까 선택적 속성의 예제와 같이 볼 수 있다.

     

     

    // 공식사이트 예제
    interface ButtonInterface {
      // 속성 이름 뒤에 ? 기호가 붙으면 옵션 속성이 됩니다.
      onInit?():void;
      onClick():void;
    }
    
    class ButtonComponent implements ButtonInterface {
    
      // onInit 메서드가 설정되지 않아도 오류를 발생하지 않습니다.
      onClick() { console.log('버튼 클릭') }
    
    }
    
    class ButtonComponent implements ButtonInterface {
    
    	// 아무 메서드도 정의 되어 있지 않다면 에러 발생
      }

     

     

    interface는 사용할 프로퍼티와 타입을 분리하여 사용할 수 있는 방법입니다. 이처럼 interface를 사용할 경우 동일한 데이터를 여러 번 사용할 때 반복해서 프로터티나 타입 등을 선언하지 않아도 된다는 장점이 있다.

     

     

    // 인터페이스 만들기
    interface ISite {
      no: number;
    }
    
    // 객체에 인터페이스 사용하기
    const mySite: ISite = {
      no: 1
    };
    
    // 함수에 인터페이스 사용하기
    const getSiteNo = (site: ISite) => {
      return site.no;
    };

     

     

    타입 에너테이션을 제공하지 않으면 any로 간주

    다중 인터페이스로도 구현 가능하다(개수 제한 없이 인터페이스 사용 가능)

     

    class Site implements ISite, IFavorite {
    }

     

     

    🔗 클래스 확장

    클래스는 확장이 가능

    확장하는 개념에서 타입스크립트는 타입 검사를 추가한다.

     

     

    풀스택, 백엔드, 프론트엔드 개념으로 알아보기

     

    export class FrontEnd {
        public frontEndSkills = ["html", "css", "js"]
    public react = () => {
            console.log('I write code with React')
        }
    }
    // FrontEnd.ts
    
    // 확장해주면 FrontEnd.ts의 멤버 변수와 메소드에 접근 가능
    export class FullStack extends FrontEnd{
        public name: string
        public age: number
    constructor(name: string, age: number) {
            super()
            this.name = name
            this.age = age
        }
    }
    // FullStack.ts

     

    🤷🏻 백엔드를 추가하고 싶다면?

     

    export interface BackEndType {
        backendSkills: Array<string>
        django: () => void
    }
    export class BackEnd {
        public backendSkills = ["database", "aws", "restapi"]
    public django() {
            console.log('I build things with django')
        }
    }
    // BackEnd.ts
    
    export class FullStack extends FrontEnd, BackEnd{ // Error
        public name: string
        public age: number
    constructor(name: string, age: number) {
            super()
            this.name = name
            this.age = age
        }
    }
    //Error FullStack.ts

     

    mixin 함수를 추가

    프론트엔드클래스를 상속받은 풀스택 클래스 베이스 클래스로 만들어 백엔드 클래스와 확장해주면 된다.

     

     

    const FullStackExtension = <T extends Constructor>(baseClass: T) => {
        return class FrontEnd extends baseClass {
            public frontEndSkills = ["html", "css", "js"] as const
    public react = () => {
                console.log('I write code with React')
            }
        }
    }
    // FullStack.ts
    
    
    export class FullStack extends FullStackExtension(BackEnd) {
        public name: string
        public age: number
    constructor(name: string, age: number) {
            super()
            this.name = name
            this.age = age
        }
    }
    // FullStack.ts

     

     

    🔗 재정의된 생성자, 메서드, 속성

     

    생성자

     

    JS에서 상속받은 하위 클래스에서는 자체 생성자가 없고 기본 클래스의 생성자를 사용

    super라는 키워드를 통해 생성자를 호출한다.

    TS에서는 기본클래스의 생성자를 호출 할 때 올바른 매게변수를 사용했는지 확인

    예를 들어, class B,C가 A에 상속받는 때 이때 C에서 super라는 키워드 없이 생성자를 생성하면 오류

    타입 검사기에서 super() 호풀 전에 A에 있는 메서드의 타입을 참조하기 때문이다.

     

     

    메서드

     

    하위 클래스의 메서드가 기본 클래스의 메서드에 할당될 수 있는 한 하위 클래스는 기본 클래스와 동일한

    이름으로 새 메서드를 다시 선언할 수 있다.

    기본 클래스의 모든 메서드 👉🏼👉🏼 하위 클래스에서 사용 가능 새 메서드 타입도 기본 메서드 대신 사용할 수 있어야 한다! 

     

    속성

     

    하위 클래스는 새 타입을 기본 클래스의 타입에 할당할 수 있는 한 동일한 이름으로 기본 클래스의 속성을 명시적으로 다시 선언

    재정의된 메서드와 마찬가지로 하위 클래스는 기본 클래스의 구조적으로 일치해야 한다.

    예를 들어, 기본 클래스의 grade가 number | undefined라면 하위 클래스 또한 number타입으로 선언해야 한다.

     

     

     

    🔗 추상 클래스

     

    추상 클래스를 정의할 때는 class 앞에 abstract라고 표기

    때로는 일부 메서드의 구현을 선언하지 않고, 대신 하위 클래스가 해당 메서드를 제공할 것을 예상하고

    기본 클래스를 만드는 방법이 유용할 수 있다.

     

    // 추상 클래스
    abstract class Project {
    
      public project_name:string|null = null;
      private budget:number = 2000000000; // 예산
    
      // 추상 메서드 정의
      public abstract changeProjectName(name:string): void;
    
      // 실제 메서드 정의
      public calcBudget(): number {
        return this.budget * 2;
      }
    
    }
    
    // [오류]
    // [ts] 추상 클래스의 인스턴스를 만들 수 없습니다.
    // constructor Project(): Project
    let new_project = new Project();

     

     

     

    🔗 멤버 접근성

     

    접근 제한자 public, private, protected를 지원

    #을 추가해 private 클래스 멤버임을 나타낸다.

     

    접근 범위 public protected private
    클래스 내부 O O O
    자식 클래스 내부 O O X
    클래스 인스턴스 O X X

     

     

    class Animal {
      constructor(public name: string, protected age: number, private breed: string) {
        this.name = name;
        this.age = age;
        this.breed = breed;
      }
    
      protected talk() {
        console.log(`this animal's name is ${this.name}`);
      }
    }
    
    const animal = new Animal("Ruby", 2, 'tlrhfmwkqmwhd');
    
    // error : 'talk' 속성은 보호된 속성이며 'Animal' 클래스 및 해당 하위 클래스 내에서만 액세스할 수 있습니다.
    animal.talk();
    
    class Dog extends Animal{
      constructor(name: string, age: number, breed: string) {
        super(name, age, breed);
    
        this.talk();
        console.log(this.age);
        
        // error : 'breed' 속성은 private이며 'Animal' 클래스 내에서만 액세스할 수 있습니다.
        console.log(this.breed);
      }
    }
    
    
    // this.talk(): this animal's name is Ruby
    // this.age: 5
    const dog = new Dog("Ruby", 5, 'tlrhfmwkqmwhd');

     

    🔗 정적 필드 제한자

     

    static 키워드를 사용해 인스턴스를 생성할 필요 없이, 클래스 자체에서 멤버를 선언 

    readonly의 접근성 키워드를 함께 사용할 수 있도록 지원

     

     

    class Mathmatics {
    
      // 스태틱 속성
      static PI:number = Math.PI;
    
      // 스태틱 메서드
      // circumference = 둘레(원주)
      static calcCircumference(radius:number) :number {
        return this.PI * radius * 2;
      }
    
      static calcCircleWidth(radius:number): number {
        return this.PI * Math.pow(radius, 2);
      }
    
    }
    
    // radius = 반지름
    let radius = 4;
    
    console.log('PI(원주율) = ', Mathmatics.PI);
    console.log(`반지름이 ${radius}인 원의 넓이: πr² = `, Mathmatics.calcCircleWidth(radius));
    console.log(`반지름이 ${radius}인 원의 둘레: 2πr = `, Mathmatics.calcCircumference(radius));

     

    반응형

    'codeStates front-end > Typescript' 카테고리의 다른 글

    [TS] 제네릭  (0) 2023.03.23
    [TS] 타입 제한자  (0) 2023.03.21
    [TS] 인터페이스  (0) 2023.03.12
    [TS] 배열과 튜플  (0) 2023.03.12
    [TS] 함수  (0) 2023.03.12

    댓글

Designed by Tistory.