[TypeScript] Class

youngseo·2022년 6월 10일
0

Type Script

목록 보기
7/10
post-thumbnail

클래스 소개

  • 클래스는 다른 프로그래밍 언어에서도 존재하는 문법입니다. JavaScript에서는 ES2015의 새로운 문법입니다.
  • TypeScript에서의 클래스 기능은 C#에서 유래된 것이 많습니다.
  • JS에서 제공하는 클래스와 TS에서 제공하는 클래스가 상이합니다
  • 일부 기능은 TS에서만 존재하는 고유 문법으로 컴파일 후에 사라집니다.

1. 필드

필드란 일종의 속성으로, public으로 사용 가능합니다.

class Person {
  name: string;
  age: number;
  readonly location: string = "Korea";
}

아래와 같이 자바스크립트로 컴파일이 됩니다.

2. 생성자와 인스턴스

생성자

  • 생성자는 클래스가 만들어질 때 반드시 필요하며 초기화를 담당합니다.
  • 클래스가 인스턴스화될 때 생성되는 순간에 인스턴스를 필요한 것들을 세팅하고 초기화 합니다.

인스턴스

  • 클래스에서 파생된 고유한 것으로, 실제로 생성된 후 메모리에 올라갑니다.
/**
 * Class
 */
class Person {
//필드
  name: string;
  age: number;
  readonly location: string = "Korea";

//생성자
  constructor(name: string, age: number) {
      this.name = name
      this.age = age
  }
}

//인스턴스
const p1 = new Person('Jang', 99);
const p2 = new Person('Poco', 100);

console.log(p1)
console.log(p2)

3. 매서드

  • 매서드는 클래스 관점에서 속성이 아닌 행동을 담당합니다.
  • 또한 클래스가 가지고 있는 함수를 메서드라고 표현할 수 있습니다.
class Person {
//필드
  name: string;
  age: number;
  readonly location: string = "Korea";

//생성자
  constructor(name: string, age: number) {
      this.name = name
      this.age = age
  }
}

//메서드
  introduce(): string {
    return `${this.name}의 나이는 ${this.age} 입니다.`
  }
}

//인스턴스
const p1 = new Person('Jang', 99);
const p2 = new Person('Poco', 100);

console.log(p1.introduce())
console.log(p2.introduce())

4. Getter & Setter

  • 필드에 접근할 권한을 가진 제어자
  • getter O / setter X => 속성은 자동으로 읽기 전용
  • setter 매개변수의 타입 X / getter의 반환 타입에서 추론
  • private 속성은 .연산자로 접근할 수 없다.

Getter & Setter는 필드에 접근할 수 있는 필드접근자로 clas에서 필드는 아래와 같이 큰 어려움 없이 접근할 수 있습니다.

class Person {
  name: string;
 age: number;

  constructor(name: string, age: number) {
      this.name = name
      this.age = age
  }
}

const p = new Person('Roh', 93)
//이처럼 필드에 쉽게 접근할 수 있습니다.
console.log(p.age)
console.log(p.name)

또한 클래스 필드를 이용하면 필드에 접근하는 것을 제어할 수 있습니다.

예시로 private속성을 보도록 하겠습니다.

class Person {
  name: string;
  //_ 은 숨겨진 속성을 사용할 때 사용하는 컨벤션입니다.
  private _age: number;

  constructor(name: string, age: number) {
      this.name = name
      this._age = age
  }
}

위와 같이 private속성이 사용된 부분은 에러가 발생을 하게 됩니다.

이렇게 내부적으로 숨겨진 것을 접근하기 위해 사용되는 것이 바로 getter입니다,

이렇게 getter을 설정해주면 어디서 어떻게 접근을 하든 나이를 보여주는 부분을 바꿀 수 있게 됩니다.

마찬가지로 setter을 사용해 들어오는 정보를 제한 할 수도 있습니다.

5. extends

extends는 객체지향에서 널리 알려진 개념입니다.

과연 extends키워드를 상속으로 바라볼지? 확장으로 바라볼지 고민해보는 것이 좋습니다.

class 기본 {
  result() {
    return 'Base'
  }
}

class 파생 extends 기본 {
  result() {
    return 'Derived'
  }
}

const de = new 파생()

console.log(de.result())

6. super

  • 기본 클래스 호출시 사용
  • 생성자에서 this 사용 전 호출되어야함
class Animal {
  name: string

  constructor(name: string) {
    this.name = name
  }

  sayName() {
    return `동물의 이름은 ${this.name}`
  }
}
//파생클래스
class Person extends Animal {
  constructor(name: string) {
    //animal의 생성자를 쓰고 싶을 때 super을 사용할 수 있습니다
    super(name)
  }

  sayName() {
    //this.name은 Person에 존재하지 않고 Animal에 존재를 합니다.
    return `${super.sayName()} 사람의 이름은 ${this.name}`
  }
}

this는 인스턴스를 가르키기 때문에 결국 생성된 인스턴스에서 재활용할 수 있습니다.

7. 접근제어자

  • 속성과 메서드에 접근을 제한할 수 있다.
  • 클래스 내부 구현 정보를 적당히 공개하여 일부분만 노출시킨다
    • API와 비슷한 흉내를 낼 수 있다.
    • 타입 시스텝을 이용해 규칙을 강제할 수 있다.
제어자설명
public어디서나 접근 가능 (기본값)
protected해당 클래스와 서브클래스에서만 접근 가능
private해당 클래스에서만 접근 가능
class Person {
  public name: string
  private age: number
  protected gender: 'M' | 'F'

  constructor(name: string, age: number, gender: 'M' | 'F') {
    this.name = name
    this.age = age
    this.gender = gender
  }

  sayName() {
    return `이름은 ${this.name} 입니다`
  }

  protected sayAge() {
    return `나이는 ${this.age}`
  }

  private sayGender() {
    return `성별 타입은 ${this.gender}`
  }
}

class Me extends Person {
  constructor(name: string, age: number, gender: 'M' | 'F') {
    super(name, age, gender)
  }

  sayInfo() {
    return `${super.sayGender()} ${super.sayAge()} ${super.sayName()}`
  }
}

8. static

  • 클래스의 속성과 메서드를 new로 인스턴스화 하지 않고 호출할 수 있다.
  • 접근 제어자를 활용할 수 있다.
  • 몇가지 정적 이름을 사용할 수 없다.
    • 클래스는 그 자체로 new로 호출할 수 있는 함수이기 때문
    • 예) function.name

9. readonly

readonly는 타입스크립트에서 제공되는 기능입니다. 일반적인 속성에 프리픽스로 readonly만 붙이면 쉽게 사용이 가능합니다.

자바스크립트에서는 수정할 수 있는 접근제어자가 있습니다. 이를 통해 인스턴스의 데이터를 쉽게 수정할 수 있습니다.

하지만 readonly를 통해 수정할 수 없도록 막아줄 수 있습니다. 이를 통해 안전한 클래스를 만들수 있습니다.

10. 추상클래스

  • abstract를 선언한 클래스로 직접 인스턴스화 될 수 없는 클래스이다.
  • 직접 인스턴스화 될 수 없지만 extends 후 파생된 클래스를 인스턴스화하도록 유도한다.
  • 추상 클래스는 구현된 메서드를 포함시킬 수 있다.
  • abstract 선언한 메서드는 파생된 클래스에서 메서드를 구현해야한다.
class Animal {
   //선언된 메서드
  hello()
  
  //구현된 메서드
  run(){
     return this.hello() + 'run' 
  }
}

//추상클래스는 직접 인스턴스가 될 수 없습니다.
//const animal = new Animal()

//하지만 `extends` 후 파생된 클래스를 인스턴스화하도록 유도합니다.
class Person extends Animal {
  
}

const person = new Person

만약, extends 후 파생된 클래스가 모두다 hello()라는 메서드를 포함하도록 강제시키고 싶다면 어떻게해야할까요?

abstract class Animal {
  // 선언된 메서드
  abstract hello(): string
 
  // 구현된 메서드
  run() {
    return this.hello() + ' run'
  }
}

class Person extends Animal {
 //hello()가 포함되어 있지 않기 때문에 에러가 발생합니다. 
}

class Dog extends Animal {
  hello() {
    return 'Dog'
  }
}

11. Parameter Properties

class Person {
  //필드
    public name: string,
    private age: number,
    protected gender: 'M' | 'F'
    
              //생성자매개변수
  constructor(name: string, age: number, gender: 'M' | 'F') {
    this.name = name
    this.age = age
    this.gender = gender
  }
}

타입스트립트에서 필드를 한번 만들고 생성자매개변수를 한번 더 만드는 과정이 너무 귀찮게 느껴질 수 있습니다.

public name: string,
private age: number,
protected gender: 'M' | 'F'

또한 위와 같은 접근제어자/접근제어자에 대한 필드네임/ 필드네임에 대한 타입을 Parameter Properties을 통해 한번에 생성할 수 있습니다.

위의 녀석들을 constructor의 생성자매개변수에 넣어 정의를 하는 것입니다.

class Person {
  constructor(public name: string, private age: number, protected gender: 'M' | 'F') {
    this.name = name
    this.age = age
    this.gender = gender
  }
}

또한 아래와 같이 생략도 가능합니다.

class Person {
  constructor(
    public name: string,
    private age: number,
    protected gender: 'M' | 'F'
    ) {//이부분을 생략
  }
}

12. 메서드 오버라이딩

class Animail {
   run(){
      return 'Animal이 달린다' 
   }
}

class Dog extends Animal {
  
}

class Person extends Animal {
  
}

const p = new Person()
console.log(p.run())

타입스크립트든, 자바스크립트에서든 파생된 클래스에서는 기본 베이스나 필드에 접근할 수 있는 장점이 있습니다.

class Animail {
   run(){
      return 'Animal이 달린다' 
   }
}

class Dog extends Animal {
   run(){
      return 'Dog 달린다' 
   }
}

class Person extends Animal {
   run(){
      return 'Person 달린다' 
   }
}

const p = new Person()
console.log(p.run())

위와 같이 Animal, Dog, Person모두 run이라는 메소드를 가지고 있을 때 확장된 Person이라는 클래스에서 run()메서드를 덮어써야하는 경우, 메서드 오버라이딩을 공유할 수 있습니다.

0개의 댓글