타입스크립트 정리9 : 타입스크립트 class

Kimhojin_Zeno·2023년 5월 17일
0

타입스크립트 정리

목록 보기
9/13

타입스크립트 클래스

class Player {
	first: string;
	last: string;
	score: number = 0;  // 클래스 필드 구문. 이렇게 타입 정하고 값도 넣을 수 있다.
	constructor(first: string, last: string) {
		this.firtst = first;
		this.last = last;
	}
}

const elton = new Player("Elton", "Steele");

생성자 함수 전에 first와 last 모두 타입이 설정되어야 한다.

그 다음 생성자 함수에서 받는 argument도 타입을 정해야 함.

readonly

class Player {
	readonly first: string;
	readonly last: string;
	score: number = 0;
	constructor(first: string, last: string) {
		this.firtst = first;
		this.last = last;
	}
}

const elton = new Player("Elton", "Steele");
elton.first = "elton" // 에러. 위에서 readonly로 

읽기 전용 제어자. 객체 타입 컨텍스트에서와 같이 클래스에서만 readonly를 사용할 수 있다.

public 제어자

기본적으로 JavaScript와 TypeScript의 모든 클래스 프로퍼티와 메서드는

public으로 간주한다.

즉 first(이름)과 last(성) 액세스하고 또 어디서나 score에 액세스할 수 있다.

readonly는 first를 변경할 수 없도록 한다. 하지만 접근할 수는 있음

public 접근 제어자는 클래스 외부에서 변경할 수 있도록 명시하는 것이다.

class Player {
	public readonly first: string;
	public readonly last: string;
	public score: number = 0; 
	constructor(first: string, last: string) {
		this.firtst = first;
		this.last = last;
	}
}

const elton = new Player("Elton", "Steele");

다른 개발자가 클래스 외부에서도 프로퍼티에 변경, 접근, 쓰기를 할 수 있다고 명확히 알리는 것.

public은 가시성 여부이고 readonly는 프로퍼티에 대한 쓰기 여부를 결정함.

즉 public readonly라면 공개적으로 읽을 수 있지만 퍼블릭이든 아니든 쓰기를 할수는 없다.

first와 last를 변경할 수는 없음.

Private 제어자

class Player {
	public readonly first: string;
	public readonly last: string;
	private score: number = 0;   // private 제어자

	constructor(first: string, last: string) {
		this.firtst = first;
		this.last = last;
	}
}

const elton = new Player("Elton", "Steele");

elton.score // 에러.

프로퍼티나 메서드 앞에 private이라고 붙이면

해당 프로퍼티 또는 메서드가 오직 클래스의 내부에서만 접근 및 사용할 수 있다고 정하는 것.

자바스크립트의 해시 기호 # 를 이용한 구문은 ES2015 이상 타겟으로 해야 사용가능.

자바스크립트에서 인식하는 코드이다.

private은 타입스크립트에서만 사용 가능.

#와 private의 차이점

  1. 프로퍼티 이름이 바뀜
  2. private은 런타임 전에만 오류가 뜸. 컴파일하면 사라진다.

shortcut syntax

단축 구문. 파라미터 프로퍼티 parameter property라고 부른다.

생성자를 초기화하기 전에 먼저 프로퍼티와 타입을 선언하는 위와 같은 방식은

프로퍼티가 많으면 힘들다. 그래서 단축 구문을 사용한다

class Player {
	// public readonly first: string;
	// public readonly last: string;
	// private score: number = 0;
	constructor(
		public first: string, 
		public last: string,
		private score: number
) {}
		// 별도의 파라미터를 설정할 필요도 업다. 이전에 작성한 버전과 같은 효력.
}
const elton = new Player("Elton", "Steele");

훨씬 단축해서 쓸 수 있다. 자바스크립트로 변환하면

class Player {
	constructor(first, last, score) {
		this.first = first;
		this.last = last;
		this.score = score;
	}
}

이렇게 나타난다.

실행되는 내용은 같음.

getter

자바스크립트와 같이 TypeScript는 클래스에 getter와 setter 즉 객체 접근자(accessor)를 사용할 수 있다

class Player {
	constructor(
		public first: string, 
		public last: string,
		private _score: number
	) {}

	private secretMethod(): void {
		console.log("SECRET METHOD!");
	}

	get fullName(): string {
		return `${this.first} ${this.last}`;
	}

	get score(): number { // 프라이빗 프로퍼티를 공개적으로 표시되는 getter로 감쌈.
		return this._score;
	}
	set score(newScore: number) {  // set을 사용해 로직을 추가할 수 있음.
		if(newScore < 0) {
			throw new Error ("Score cannot be negative!")
		}
		this._score = newScore;
	}

}

const elton = new Player("Elton", "Steele", 100);

elton.score = -1 // "Score cannot be negative!"

protected 키워드

상속 작업을 할때 사용된다

class Player {
	constructor(
		public first: string, 
		public last: string,
		private _score: number
	) {}
}

class SuperPlayer extends Player {
	public isAdmin: boolean = true;
	maxScore() {
		this._score = 99999;  // 오류가 난다. _score는 private 프로퍼티니까.
	}
}

그러나

private _score 를

protected _score 로 바꾸면

외부에서 _score에 액세스 하는 것은 불가능 하지만 자식 클래스는 예외가 된다.

public과는 다름. public은 어디서나 액세스되지만 protected는 자식 클래스에서만 액세스할 수 있다.

상속 클래스나 하위 클래스 없이 오직 한 클래스에서만 액세스할 수 있는 클래스를 만들고 싶다면 Private을 사용.

그 외 하위 클래스에서도 사용하고 싶고 그 외에는 불가하게 하려면 protected.

interface

인터페이스를 구현하는 클래스.

interface Colorful {
		color: string;
}

interface Printable {
	print(): void;
}

class Bike implements Colorful, Printable {  // 두개를 다 따를수도 있다
	constructor(public color: string) {}

	print() {
		console.log("print")
	}
}

const bike1 = new Bike("red")

abstract 클래스

abstract 키워드를 붙이면 이 자체로는 더 이상 새 클래스를 만들 수 없다는 뜻.

cat을 인스턴스화 하려고 하면 abstract 클래스의 인스턴스는 만들 수 없다고 뜬다.

인스턴스를 생성할 수 없는 클래스가 필요한 이유 → 패턴을 정의하고 자식 클래스에서 시행돼야 하는 메서드를 정의하는데 사용된다.

즉 자식 클래스를 쓰기 위한 패턴. 스스로는 인스턴스화 안함.

abstract class Employee {
		constructor(public first: string, public last: string) {}
		abstract getPay(): number;
		greet() {
			console.log("hello!")
		}
}

Employee의 하위 클래스의 인스턴스가 getPay라는 메서드를 호출하고 숫자로 반환해야 한다.

이 메서드는 여기에 존재하지 않음. Employee를 확장하는 모든 클래스에 존재해야 한다.

인터페이스와 비슷해보이지만 이건 실제 기능이 있는 클래스이다

greet 같은 부분. 복잡한 기능을 인터페이스에선 미리 설정해놓을 수 없다. 확장될때 자동으로 얻게 되는 추가 기능이 인터페이스는 없다.

class FullTimeEmployee extends Employee {
	constructor(first: string, last: string, private salary: number) {
		super(first, last);
	}
	getPay() { 
		 return this.salary;
	}
}

const betty = new FullTimeEmployee("betty","white", 9500);
console.log(betty.getPay()); // 9500

Employee에서 설정했듯이 숫자를 리턴하는 getPay가 반드시 있어야한다.

profile
Developer

0개의 댓글