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도 타입을 정해야 함.
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를 사용할 수 있다.
기본적으로 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를 변경할 수는 없음.
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의 차이점
단축 구문. 파라미터 프로퍼티 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;
}
}
이렇게 나타난다.
실행되는 내용은 같음.
자바스크립트와 같이 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!"
상속 작업을 할때 사용된다
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 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 키워드를 붙이면 이 자체로는 더 이상 새 클래스를 만들 수 없다는 뜻.
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가 반드시 있어야한다.