PracticeEveryday
Class 본문
1. 클래스 정의
- ES6 클래스는 몸체에 메소드만을 포함할 수 있다. 클래스 몸체에 클래스 프로퍼티를 선언할 수 없고 반드시
생성자 내부에서 클래스 프로퍼티를 선언하고 초기화한다.
// person.js
class Person {
constructor(name) {
// 클래스 프로퍼티의 선언과 초기화
this.name = name;
}
walk() {
console.log(`${this.name} is walking.`);
}
}
이 코드의 확장자를 .ts로 바꾸어 컴파일하면 에러가 난다.
person.ts(4,10): error TS2339: Property 'name' does not exist on type 'Person'.
person.ts(8,25): error TS2339: Property 'name' does not exist on type 'Person'.
※ TypeScript 클래스는 클래스 몸체에 클래스 프로퍼티를 사전 선언하여야 한다.
class Person {
// 클래스 프로퍼티를 사전 선언하여야 함
name: string;
constructor(name: string) {
// 클래스 프로퍼티에 값을 할당함.
this.name = name;
}
walk() {
console.log(`${this.name} 걷는 중 ..`)
}
}
2. 접근 제한자
- TypeScript 클래스는 클래스 기반 객체 지향 언어가 지원하는 접근 제한자 ( Access modifier )
public, private, protected를 지원하며 의미 또한 기본적으로 동일하다.
- 접근 제한자를 명시하지 않을 때
타 클래스 기반 언어 : 암묵적으로 protected로 지정
타입스크립트 : 암묵적으로 public 선언
- 접근 제한자를 선언한 프로퍼티와 메소드에 대한 접근 가능성
접근 가능성publicprotectedprivate
접근 가능성 | public | protected | private |
클래스 내부 | ◯ | ◯ | ◯ |
자식 클래스 내부 | ◯ | ◯ | ✕ |
클래스 인스턴스 | ◯ | ✕ | ✕ |
class Foo {
public x: string;
protected y: string;
private z: string;
constructor(x: string, y: string, z: string) {
// public, protected, private 접근 제한자 모두 클래스 내부에서 참조 가능하다.
this.x = x;
this.y = y;
this.z = z;
}
}
const foo = new Foo("x", "y", "z");
// public 접근 제한자는 클래스 인스턴스를 통해 클래스 외부에서도 참조가 가능하다.
console.log(foo.x);
// protected 접근 제한자는 클래스 인스턴스를 통해 클래스 외부에서 참조할 수 없다.
console.log(foo.y);
// private 접근 제한자는 클래스 인스턴스를 통해 클래스 외부에서 참조할 수 없다.
console.log(foo.z);
class Bar extends Foo {
constructor(x: string, y: string, z: string) {
super(x, y, z);
// public 접근 제한자는 자식 클래스 내부에서 참조 가능하다.
console.log(this.x);
// protected 접근 제한자는 자식 클래스 내부에서 참조 가능하다.
console.log(this.y);
// private 접근 제한자는 자식 클래스 내부에서 참조 할 수 없다.
console.log(this.z);
}
}
3. 생성자 파라미터에 접근 제한자 선언
- 접근 제한자는 생성자 파라미터에도 선언할 수 있다.
- 이 때 접근 제한자가 사용된 생성자 파라미터는 암묵적으로 프로퍼티로 선언되고 생성자 내부에서 별도의 초기화가
없어도 암묵적으로 초기화가 수행된다.
- 이 때 private 접근 제한자가 사용되면 클래스 내부에서만 참조 가능하고 public 접근 제한자가 사용되면 클래스
외부에서도 참조가 가능하다.
class Foo2 {
// 접근 제한자가 선언된 생성자 파라미터 x는 클래스 프로퍼티로 선언되고 자동 초기화 된다.
// public으로 선언되었으므로 x는 클래스 외부에서도 참조가 가능하다.
constructor(public x: string) {}
}
const foo2 = new Foo2("Hello");
console.log(foo2); // {x : "Hello"}
console.log(foo2.x); // Hello
class Bar2 {
// 접근 제한자가 선언된 생성자 파라미터 x는 멤버 변수로 선언되고 자동으로 초기화된다.
// private이 선언되었으므로 x는 클래스 내부에서만 참조 가능하다.
constructor(private x: string) {}
}
const bar2 = new Bar2("Hello");
console.log(bar2); // { x: "Hello" }
console.log(bar2.x);
//'x' 속성은 private이며 'Bar2' 클래스 내에서만 액세스할 수 있습니다.
- 만일 생성자 파라미터에 접근 제한자를 선언하지 않으면 생성자 파라미터는 생성자 내부에서만 유효한 지역 변수가
되어 생성자 외부에서 참조가 불가능하게 됩니다.
class Foo3 {
constructor(x: string) {
// 생성자 파라미터는 생성자 내부에서만 유효한 지역 변수이다.
console.log(x)
}
}
const foo3 = new Foo3("Hello")
console.log(foo3) // Foo3: {}
4. readonly 키워드
- readonly가 선언된 클래스 프로퍼티는 선언 시 또는 생성자 내부에서만 값을 할당할 수 있다.
- 그 외에는 값을 할당 할 수 없고 오직 읽기만이 가능한 상태가 된다.
class Foo4 {
private readonly MAX_LEN: number = 5;
private readonly MSG: string = "Hello";
log() {
this.MAX_LEN = 10;
// 읽기 전용 속성이므로 'MAX_LEN'에 할당할 수 없습니다
this.MSG = "Hi";
// 읽기 전용 속성이므로 'MAX_LEN'에 할당할 수 없습니다
console.log(`MAX_LEN: ${this.MAX_LEN}`);
console.log(`MSG: ${this.MSG}`);
}
}
new Foo4().log();
5. static 키워드
- ES6 클래스에서 static 키워드는 클래스의 정적 ( static ) 메소드를 정의한다.
- 정적 메소드는 클래스의 인스턴스가 아닌 클래스의 이름으로 호출한다.
=> 인스턴스를 생성하지 않아도 호출할 수 있다.
class Foo {
constructor(prop) {
this.prop = prop;
}
static staticMethod() {
/*
정적 메소드는 this를 사용할 수 없다.
정적 메소드 내부에서 this는 클래스의 인스턴스가 아닌 클래스 자신을 가리킨다.
*/
return 'staticMethod';
}
prototypeMethod() {
return this.prop;
}
}
// 정적 메소드는 클래스 이름으로 호출한다.
console.log(Foo.staticMethod());
const foo = new Foo(123);
// 정적 메소드는 인스턴스로 호출할 수 없다.
console.log(foo.staticMethod()); // Uncaught TypeError: foo.staticMethod is not a function
- TypeScript에서는 static 키워드를 클래스 프로퍼티에도 사용할 수 있다.
- 정적 메소드와 마찬가지로 정적 클래스 프로퍼티는 인스턴스가 아닌 클래스 이름으로 호출하며 인스턴스를 생성
하지 않아도 호출할 수 있다.
class Foo5 {
// 생성된 인스턴스 갯수
static instanceCounter = 0;
constructor() {
Foo5.instanceCounter++;
}
}
const foo5 = new Foo5();
const foo52 = new Foo5();
console.log(Foo5.instanceCounter);
console.log(foo5.instanceCounter);
// 'instanceCounter' 속성이 'Foo5' 형식에 없습니다. 대신 정적 멤버 'Foo5.instanceCounter'에 액세스하려고 하셨습니까?
6. 추상 클래스
- 추상 클래스 ( abstract class )는 하나 이상의 추상 메소드를 포함하며 일반 메소드도 포함할 수 있다.
- 추상 메소드는 내용이 없이 메소드 이름과 타입만이 선언된 메소드를 말하며 선언할 때 abstract 키워드를 사용한다.
- 추상 클래스를 정의할 때는 abstract 키워드를 사용하며, 직접 인스턴스를 생성할 수 없고 상속만을 위해 사용한다.
- 추상 클래스를 상속한 클래스는 추상 클래스의 추상 메소드를 반드시 구현해야 한다.
abstract class Animal {
// 추상 메소드
abstract makeSound(): void;
move(): void {
console.log("roaming the earth ...");
}
}
// 직접 인스턴스를 생성할 수 없다.
new Animal();
// 추상 클래스의 인스턴스를 만들 수 없습니다.
class Dog extends Animal {
// 추상 클래스를 상속한 클래스는 클래스의 추상 메소드를 반드시 구현해야 한다.
makeSound() {
console.log("Bowwow~!");
}
}
const dog1 = new Dog();
dog1.makeSound();
dog1.move();
- 인터페이스는 모든 메소드가 추상 메소드이지만 추상 클래스는 하나 이상의 추상 메소드와 일반 메소드를 포함할
수 있다!
TypeScript - Class | PoiemaWeb
ES6에서 새롭게 도입된 클래스는 기존 프로토타입 기반 객체지향 언어보다 클래스 기반 언어에 익숙한 개발자가 보다 빠르게 학습할 수 있는 단순명료한 새로운 문법을 제시하고 있다. 하지만
poiemaweb.com
'JavaScript > TypeScript' 카테고리의 다른 글
TypedI (0) | 2022.08.25 |
---|---|
TypeScript (0) | 2022.06.14 |
TypeScript (0) | 2022.06.10 |
TypeScript (0) | 2022.06.10 |
TypeScript (0) | 2022.06.04 |