TypeScript Classes 정리

일상 코딩·2022년 4월 9일
0

TypeScript

목록 보기
11/12

01.What are Classes?

  • object를 만드는 blueprint(청사진, 설계도)
  • JavaScript에도 es6부터 class 키워드 사용 가능
  • TypeScript에서는 클래스도 사용자가 만든 타입의 하나

02.Quick Start - Class

  • class 키워드를 이용하여 클래스를 만들 수 있다.
  • class 이름은 보통 대문자를 이용한다.
  • new를 이용하면 class를 통해 object를 만들 수 있다.
  • constructor를 이용하면 object를 생성하면서 값을 전달할 수 있다. (Java의 class 생성자와 유사)
  • this 를 이용하면 만들어진 object를 가리킬 수 있다.
  • TSJS로 컴파일되면 es5의 경우 function으로 변경된다.
class Person { // class 이름은 대문자로 시작
  name;
  // 생성자 함수
  constructor(name: String) { 
    this.name = name;
  }
 }

// Person obj를 p1에 할당 (새로운 p1 객체를 생성)
const p1 = new Person("Mark");

console.log(p1);

03.constructor & initialize

  • 프로그래머가 직접 생성자를 정의하지 않으면 default 생성자가 동작한다.
  • 프로그래머가 constructor를 이용해 직접 생설자를 정의하면 default 생성자는 사라진다.
  • default 생성자는 매개변수 없이 사용되는 생성자 함수를 의미한다.
  • 클래스의 프로퍼티가 정의되어 있지만, 값을 대입하지 않으면 undefined 이다.
  • 생성자에는 async를 설정할 수 없다.
class Person {
  ame: String = "Mark"; // 직접 할당 => 초기값을 설정해주지 않으면 오류발생!
  age: Number;

  // async constructor (x)
  constructor(age?: Number) {
    if(age === undefined) {
      this.age = 20;
    } else {
      this.age=age;
    }
  }
 }

// 이런 형태 두개 다 지원하려고 한다면 각각의 생성자 생성(오버로딩)
// 오버로딩 => 같은 이름, 다른 매개변수
// JS에서는 오버로딩이 안됨. TS에서는 가능.
const p1 = new Person(39);
const p2 = new Person();

console.log(p1);
console.log(p1.age);

클래스 프로퍼티

직접 할당

class Person {
  name: string = "Kim"; 
}
  • strict 모드에서는 프로퍼티를 선언하는 곳 또는 생성자에서 값을 할당해야 한다.

생성자 함수 사용

class Person {
  name: string; 
 
  constructor(name: string){
    this.name = name;
  }
}

동적 할당

// 사용 1
class Person {
  name!: string; // !는 초기값을 class 영역 안이 아닌 밖에서 값을 직접 설정 한다는 의미다.
}
const p1: Person = new Person();
p1.name // 값을 아직 할당 하지 않았으므로 undefined
p1.name = "Lee"; // 동적 할당

// 사용 2
class Person1 {
  name!: string; // ! 사용

  async init(name){
    this.name = name; // 비동기로 초기화
  }
}
  • 프로퍼티를 선언하는 곳 또는 생성자에서 값을 할당하지 않는 경우에는 !를 붙여서 위험을 표현한다.

sync - 동시에 일어난다는 의미이며 요청과 결과가 동시에 일어납니다. (동기)
async - 동시에 일어나지 않는다를 의미이며 요청과 결과가 동시에 일어나지 않습니다. (비동기)


04.접근 제어자 (Access Modifiers)

  • 접근 제어자에는 public, private, protected가 있다.
  • 설정하지 않으면 public 이다.
  • 클래스 내부의 모든 곳에 (생성자, 프로퍼티, 메서드) 설정 가능하다.
  • private 으로 설정하면 클래스 외부에서 접근할 수 없다.
  • 자바스크립트에서 private 지원하지 않아 오랫동안 프로퍼티나 메서드 이름 앞에 _를 붙여서 표현했다.
class Person {
  public name: string = "Kim";
  private age: 10;
}
const p: Person = new Person();
console.log(p.name); // Kim
console.log(p.age); // 에러 (클래스 외부에서 접근 불가)

생성자함수 매개변수

  • 생성자 함수의 매개변수에 접근제어자를 붙여 간편하게 작성 가능
class Person{
  public constructor(public name: string, private age: number){}
}

const p: Person = new Person("Kim",20);
console.log(p); // { name: 'Kim', age: 20 } 전체 데이터 조회는 가능
console.log(p.name); // Kim
console.log(p.age); // 에러 (직접 접근 불가)
// 접근제어자 public, private
class Person {
  public name: String = "Mark";
  // JS에서는 오랫동안 private가 없어서 _age 이런 식으로 이름에 표기를 해둠
  // JS에서는 아직도 관행이 남아서 private는 _를 붙여줌.
  private age: Number;

  public constructor(age?: Number) {
    if(age === undefined) {
      this.age = 20;
    } else {
      this.age=age;
    }
  }

  public async init() { }
 }

const p1 = new Person(39);

console.log(p1);
  • 자바스크립트는 private를 지원하지 않아 오랬동안 이름 앞에 _를 붙여서 표현했다.

public: 외부 클래스가 자유롭게 사용할 수 있도록 합니다.
protected: 같은 패키지 또는 상속관계에 있는 자식 클래스에서 사용할 수 있도록 합니다.
private: 외부에서 사용될 수 없도록 합니다.


05.initialization in constructor parameters

  • 생성자의 파라미터를 받아서 그 클래스의 프로퍼티로 초기화 하는 방법
class Person {
  public constructor(public name: String, public age: Number) { // 파라미터에 public을 붙여줌
  }
 }

const p1 = new Person("Mark", 39);

console.log(p1); // Person { name: 'Mark', age: 39 }
class Person {
  public constructor(public name: String, private age: Number) { // age는 외부에서 접근 불가
  }
 }

const p1 = new Person("Mark", 39);

// p1.age = 24; => 이거 안됨 (private)
console.log(p1); // Person { name: 'Mark', age: 39 }

06.Getters & Setters

class Person {
  public constructor(private _name: String, public age: Number) {
}
 
get name() { // 접근자
  return this._name + "Lee";
}

set name(n: String) { // 설정자 
  this._name=n;
 }
}

const p1 = new Person("Mark", 39);

console.log(p1.name); // get을 하는 함수: getter
p1.name = "Woongjae" // set을 하는 함수: setter
console.log(p1.name);

07.readonly properites

  • set은 할 수 없고 get만 할 수 있는 키워드
  • readonly : 수정불가능하게 막아 놓을 때 사용. (읽기 전용)
class Person {
  // readonly키워드를 사용하면 프로퍼티 정의 부분애서만 값 초기화 가능
  public readonly name: String = "Mark";
  private readonly country: String;

  public constructor(private _name: String, public age: Number) { 
   // readonly키워드를 사용하면 constructor 생성자 안에서만 this로 값 초기화 가능
   // 다른 메소드에서는 초기화 불가능! 
   this.country = "Korea"; 
  }
   hello() {
     // readonly이므로 수정 불가
     // this.country = "China";
  }
}

const p1 = new Person("Mark", 39);
console.log(p1.name); // get을 하는 함수 getter
// p1.name = "Lee" // set을 하는 함수 setter
console.log(p1.name); // get을 하는 함수 getter
  • 프로퍼티 값 고정, 프로퍼티 정의 부분과 생성자 함수 안에서만 값 초기화 가능

08.Index Signatures in class

  • 프로퍼티를 동적으로 생성(초기값 설정x)
// class => object를 만들어내는 청사진
// {mark: 'male', jade: 'male'}
// {chloe: 'female', alex: 'male', anna: 'female'}

class Students {
	// [index: string]: String;
    [index: string]: 'male' | 'female'; // string, 항상 male or female로 설정
    mark: "male" = "male";
}

const a = new Students();
a.mark = "male";
a.jade = "male";

console.log(a);

const b = new Students();

b.chloe = "female";
b.alex = "male";
b.anna = "female";

console.log(b);

09.Static Properites & Methods

  • 객체(인스턴스)가 아닌 클래스만 사용가능한 프로퍼티 & 메서드
class Person{
  public static CITY = "a"; // Person 클래스만 호출 가능
  public city = "a"; // 객체만 호출 가능
 
  public static hello(){} // Person 클래스만 호출 가능

  public hi(){} // 객체만 호출 가능
}

const p: Person = new Person();
Person.hello() // ok
p.hello() // 에러

Person.hi() // 에러
p.hi() // ok
class Person {
  private static CITY = "Seoul";
  public hello() {
    console.log("hello", Person.CITY);
  }

  public change() {
    Person.CITY = "LA";
  }
}

const p1 = new Person();
p1.hello(); // Seoul

const p2 = new Person();
p2.hello(); // Seoul

p1.change(); // Person.CITY 값 변경
p2.hello(); // LA
  • static 프로퍼티는 객체간 공유가 가능하다.

10.Singletons

  • 어플리케이션이 실행하는 동안 한 하나의 객체만 만들어서 사용하는 패턴
  • 생성자함수를 private로 설정함으로써 new키워드를 통한 객체 생성 막기
class ClassName {
private static instance: ClassName | null = null;
public static getInstance(): ClassName {
  // ClassName으로 만든 object가 없으면 생성
  if(ClassName.instance === null) {
    ClassName.instance = new ClassName(); // 내부에서 생성자 함수 사용 가능 (클래스 안에서 새로운 객체를 생성 후 정적 변수에 할당)
  }
  // 새로 생성한 object를 리턴
  return ClassName.instance;
  }
  private constructor() { } // private로 외부에서 new를 이용해 생성자 함수 사용 불가능 하도록 막음
} 

const a = ClassName.getInstance(); // 처음에는 만들어서 리턴
const b = ClassName.getInstance(); // 두번째 부터는 만들어진 것을 가져와서 리턴

console.log(a === b); // true (같은 object)

11.상속(interitance)

  • 클래스가 다른 클래스를 가져다가 자신만의 속성을 추가해서 사용하는 것
class Parent {
  // protected : 외부에서는 사용 불가하지만 상속하면 사용 가능
  constructor(protected _name: String, private _age: Number) { }

  public prtint(): void {
      console.log(`이름은 ${this._name} 이고, 나이는 ${this._age} 입니다.`)
  }

  protected printName(): void {
    console.log(this._name, this._age);
  }
}

// const p = new Parent("Mark", 39);
// p.prtint(); // 이름은 Mark이고, 나이는 39입니다.

class Child extends Parent {
  // 자식 클래스에 생성자가 없으면 부모 클래스의 생성자를 그대로 사용함
  // 만약 부모 클래스에 생성자가 없으면 부모 클래스의 default 생성자를 가져온다.
  public gender = "male";

  // 생성자 overide (재정의)
  constructor(age: number) {
    // 상속받는 부모 클래스의 생성자를 꼭 호출해야함! (중요!)
    // 그리고 자식의 생성자에서는 무조건 super 먼저 호출
    super("Mark Jr.", age);
    this.printName();
  }
}

const c = new Child(1);
c.prtint();
// Mark Jr. 1
// 이름은 Mark Jr.이고, 나이는 1 입니다.

12.추상 클래스(Abstract Classes)

  • 완전하지 않은 클래스를 표현
  • 추상 클래스는 new를 통한 객체 생성 불가능
  • 자식 클래스는 추상 클래스를 상속 받으면 추상 메소드를 완전하게 만들어서 구현 해야된다.
  • 추상 클래스 또는 메소드는 앞에 abstract 키워드를 붙여줘야 한다.
abstract class AbstarctPerson {
  protected _name: String = "Mark"; // 프로퍼티 선언 가능
 
  abstract setName(name: String): void; // 추상 메소드는 선언부만 작성하고 구현부는 작성하지 않는다.
}

// new AbstarctPerson();

class Person extends AbstarctPerson {
   // 추상 메소드 overide (재정의) => 반드시 추상 메소드를 정의해야한다.
  setName(name: String): void {
    this._name = name;
  }  
}

const p = new Person();
p.setName();
profile
일취월장(日就月將) - 「날마다 달마다 성장하고 발전한다.」

0개의 댓글