ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Typescript(3) - 클래스 패턴
    웹 개발/typescript 2023. 6. 4. 13:16

    클래스 상속 

    - 클래스 상속에 extends 키워드를 사용하여 수퍼 클래스의 속성을 그대로 상속받아올 수 있다. 

    - 오버라이딩 : 자바에서도 자주 나오는 문법 형태로, 부모 클래스(수퍼 클래스)로부터 상속받아온 속성을 다른 값으로 덮어쓰는 것을 의미한다.

    - 클래스 > 메서드, 속성, 인스턴스 > 함수> 클래스 안에서 정의된 속성을 가져와서 사용 

     

    가장 기초적인 상속 형태 

    // Book 수퍼 클래스를 상속 받은 E_Book 클래스
    class E_Book extends Book {
      // paper_type 오버라이딩
      paper_type = '스크린';
    }

     

    constructor & super

    - 수퍼 클래스를 상속받은 서브 클래스는 수퍼 클래스의 기능에 더하여 좀 더 많은 기능을 갖도록 설계하는 것이 자식 컴포넌트에서 부모를 상속받는 이유이다. 

    - 따라서 기존 부모의 속성 + 부모 속성 수정 + 새로운 속성 추가 = 자식 클래스(서브 클래스)라고 생각하면 된다. 

    - constructor

         - 상속 받은 부모 클래스의 생성자를 서브 클래스의 생성자로 덮어쓸 수 있도록 함

         - 즉 부모의 물려받은 속성을 서브 클래스의 consructor로 그대로 쓰는 것과 동시에 수정이 가능하다.  

     

    - super()

          - 수퍼 클래스의 생성자에 요구되는 인자를 전달해야 한다.

          - 기본 클래스 호출시 사용된다.

         - 생성자에서 this 사용 전에 호출되어야 한다.

         - this.name은 name이라고 생각하면 되고, 파생클래스에서 인자를 전달할 때 사용한다. 

         - 수퍼 클래스 constructor를 덮어쓰기 위해서는 super() 실행이 필요함 

    // 기본 클래스 
    class Actor {
      name: string
    
      constructor(name: string) {
        this.name = name;
      }
      actorName() {
        return `배우의 이름은 ${this.name}`;
      }
    }
    // 파생 클래스
    class Person extends Actor {
      constructor(name: string) {
        super(name);
      }
      personName() {
        return `${super.actorName()} 사람의 이름은 ${this.name}`;
       
      }
    }
    const person = new Person('Jongseok');
    
    console.log(person.personName());

     

    1. 매개 변수로 Jonseok을 넣는다. 

    - 즉, person이라는 변수 안에 Person클래스(파생클래스)안으로 Jonseok이 들어감. 이때 파생클래스는 부모 클래스의 내용을 상속을 받았을 뿐이지, 외부 클래스이므로 바로 접근이 가능하다. 

     

    2. 파생 class의 생성자 함수(constructor)로 Jongseok이 들어간다.

    class Person extends Actor {
    constructor(name: string) {
    super(name);
    }

     

    3. 생성자 함수에서 상위의 기본 클래스인 name으로 Jongseok이 들어가게 된다. 즉, super은 자식 클래스에서 부모 클래스로 연결해주는 징검다리 같은 친구라고 생각하면 됨!

    super(name);

     

     

    4. 기본 클래스의 name으로 들어가게 된다. 

     

     

     

     

     

     

    - 수퍼 클래스의 protected 속성은 서브 클래스에서 접근 가능한 반면, private속성은 접근이 불가능하다. 

    class E_Book extends Book {
    
      constructor(
        title:string, 
        author:string, 
        pages:number, 
        public is_downloadable:boolean
      ){
    
        super(title, author, pages);
        this.is_downloadable = is_downloadable;
    
        // 수퍼 클래스의 protected 속성은 접근 가능
        console.log(this.paper_type);
    
        // 수퍼 클래스의 private 속성은 접근 불가능
        // [오류]
        // [ts] '_manufacturing_plant' 속성은 private이며 'Book' 클래스 내에서만 액세스할 수 있습니다.
        // (property) Book._manufacturing_plant: string
        console.log(this._manufacturing_plant);
    
      }
    
    }

     

     

    getter & setter

    - 비공개로 설정할 필요가 있는 속성을 private로 설정한 후, 이 속성에 접근하여 값을 읽거나, 쓰기 위한 Getter, Setter 함수를 사용하여 속성을 정의할 수 있다. 

     

    - getter : 멤버 변수의 값을 호출함

    get 속성이름() {
       return this.속성이름
    }

     

    - setter : 멤버 변수의 값을 설정(수정)함

    set 속성함수(매개변수 : 매개변수타입){
        ...
        this.위의속성 = 매개변수;
    }

     

    class Plant {
    
      // 비공개 속성 '종(Species)'
      private _species:string|null = null;
    
      // getter 함수
      // private 속성에 함수 내부에서 접근하여 사용할 수 있도록 함 
      get species(): string {
        return this._species;
      }
    
      // setter 함수
      // getter와 항상 붙어다니는 친구로 getter에서 접근하여 private 속성을 상속받아 사용할 수 있도록 함 
      set species(value:string) {
        if ( value.length > 3 ) { this._species = value; }
      }
    
    }
    
    
    /* 인스턴스 생성 ------------------------------------------------ */
    
    let plant = new Plant();
    
    console.log(plant.species); // null
    
    plant.species = '줄기';
    
    console.log(plant.species); // null
    
    plant.species = '푸른 식물';
    
    console.log(plant.species); // '푸른 식물'

     

     

    스태틱 속성/메서드 

    - 클래스를 통해 인스턴스를 생성할 필요 없이, 클래스의 속성 또는 메서드를 사용할 때 사용함 

    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));

     

     

    추상클래스

    - class 앞에 abstract라고 표기(추상메서드도 마찬가지임)

    - 추상 메소드는 정의만 있을 뿐 몸체(body)가 구현되어 있지 않다(추상클래스 ). 몸체는 추상 클래스를 상속하는 클래스에서 해당 추상 메소드를 통해 필히 구현해야 한다.

    - 추상 클래스는 추상 메서드 뿐만 아니라, 실 사용이 가능한 메서드도 정의하는 것이 가능하다. 추상 클래스를 상속하는 클래스를 통해 생성된 인스턴스는 이 메서드를 사용할 수 있는 것이 가능하나, 추상 클래스는 말 그대로 추상이므로 클래스와 달리 인스턴스를 생성하지 않는다.

    // 추상 클래스
    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();  //이거 오류뜸 : 추상 클래스의 인스턴스를 만들어서 매개변수를 집어넣는 것은 불가능하다.

     

    - 몸체는 추상 클래스를 상속하는 클래스에서 해당 추상 메소드를 통해 반드시 구현해야 한다. 

    - 즉, Project 추상 클래스를 상속 받은 WebProject 클래스는 추상 클래스 내에 정의된 추상 메서드를 반드시 구현해야 한다.

    // 클래스 ⟸ 추상 클래스 상속
    // 반드시 Projec에서 구현한 추상메서드를 WebProject 안에서 구현해야 한다. 
    class WebProject extends Project {
      // [오류]
      // [ts] 비추상 클래스 'WebProject'은(는) 'Project' 클래스에서 상속된
      // 추상 멤버 'changeProjectName'을(를) 구현하지 않습니다. (오류 발생)
      // class WebProject
    }

     

    - 추상 클래스를 상속하는 클래스는 추상 클래스에 정의된 메서드를 구현한 예시 

    - 추상클래스를 상속하는 일반 클래스는 일반적인 클래스이기 때문에 인스턴스를 생성하는 것이 가능하다. 

    class WebProject extends Project {
    
      // 위의 추상 클래스에 정의된 추상 메서드 구현
      changeProjectName(name:string): void {
        this.project_name = name;
      }
    
    }
    
    
    /* 인스턴스 생성 ------------------------------------------------ */
    
    let new_project = new WebProject();
    
    console.log(new_project.project_name); // null
    
    new_project.changeProjectName('CJ 올리브 네트웍스 웹사이트 개편');
    
    console.log(new_project.project_name); // 'CJ 올리브 네트웍스 웹사이트 개편'

     

     

    싱글턴 

    - private 접근 제어자를 사용해 constructor() 앞에 붙이면 new 키워드를 통해 인스턴스를 생성하지 못하도록 제한할 수 있다. 하지만 이 과정은 굉장히 복잡하고, 코드를 낭비하기 때문에 타입스크립트에서는 특이한 스태틱 매서드를 통해서 인스턴스 구현 횟수를 제한해 놓았음

    - getInstance() : 오직 한 번만 인스턴스를 생성할 수 있도록 인스턴스 횟수를 제한한 스태틱 메서드이며, 싱글턴 패턴 구현의 핵심이다. 

    class OnlyOne {
    
      private static instance: OnlyOne;
    
      public name:string;
    
      // new 클래스 구문 사용 제한을 목적으로
      // constructor() 함수 앞에 private 접근 제어자 추가
      private constructor(name:string) {
        this.name = name;
      }
      
      // 오직 getInstance() 스태틱 메서드를 통해서만
      // 단 하나의 객체를 생성할 수 있습니다.
      public static getInstance() {
        if (!OnlyOne.instance) {
          OnlyOne.instance = new OnlyOne('싱글턴 객체');
        }
        return OnlyOne.instance;
      }
      
    }
    
    
    /* 인스턴스 생성 ------------------------------------------------ */
    
    // [오류]
    // [ts] 'OnlyOne' 클래스의 생성자는 private이며 클래스 선언 내에서만 액세스할 수 있습니다.
    // constructor OnlyOne(name: string): OnlyOne
    let bad_case = new OnlyOne('오류 발생');
    
    let good_case = OnlyOne.getInstance();

     

     

    읽기전용 속성(ReadOnly)

    -

Designed by Tistory.