0%

타입 스크립트 클래스

1. 타입 스크립트 클래스의 정의(class Definition)

ES6 클래스는 클래스 몸체에 메소드 만을 포함할 수 있다. 클래스 몸체에 클래스 프로퍼티를 선언 할 수 없고 반드시 생성자 내부에 클래스 프로퍼티를 선언하고 초기화 한다.

1
2
3
4
5
6
7
8
9
10
//person.js
class Person{
constructor(name){
//클래스 프로퍼티의 선언과 포기화
this.name = name
}
walk(){
console.log(`${this.name} is Walking`);
}
}

위 예제의 Es6에서의 문제없이 실행되는 토드이지만 위 파일의 확장자를 ts로 바꿔 TypeScript 파일로 변경항 후 , 컴파일하면 아래와 같이 컴파일 에러가 발생한다.

1
2
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 클래스는 클래스 몸체에 클래스 프로퍼티를 사전 선언하여여한다

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person{
//클래스 프로퍼티를 사전 선언해야 힌다.
name:string;
constructor(name){
//클래스 프로퍼티수에 값을 할당
this.name = name;
}
walk(){
console.log(`${this.name} is Walking`);
}
}
const person = new Person('kim')
person.walk(); // kim is Walking

2. 접근제한자

TypeScript 클래스는 클래스 기반 객체 지향언어가 지원하는 접근제한자 public , private,proteted를 지워하며 의미 또하 기본적으로 동일 하다.

단 , 접근제한자를 명시하지 않았을때 , 다른 클래스 기반의 언어의 경우 , 암묵적으로 protected 로 지정 되어 패키지 레벨로 공개되지만 TypeScript의 경우 , 접근 제한자르르 생략한 클래스 프로퍼티와 메소드는 암묵적으로 public 이 선언 된다. 따라서 public으로 지정 하고자하는 멤버 변수와 메소드는 접근자 제한자를 생략한다 .

접근 제한자를 선언하 프로퍼티와 메소드에 대한 접근 가능성은 다음과 같다.

접근 가능성 public protected private
클래스 내부
자식 클래스 내부
클래스 인스턴스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 접근 제한자가 사용되면 클래스 외부에서도 참조가 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Foo{
//접근 제한자가 선언된 생성자 파라미터 x는 클래스 프로퍼티로 선언되고 자동으로 초기화 된다.
//public이 선언되었으므로 x는 클래스 외부에서도 참조가 가능하다.
constructor(public x:string){}
}

const foo = new Foo('hello');
console.log(foo) Foo {x:'hello'};
console.log(foo.x) //hello

class Bar{
//접근 제한자가 선언된 생성자 파라미터 x는 멤버 변수로 선언되고 자동으로 초기화된다.
//private이 선언되었으므로 x는 클래스 내부에서만 참조 가능하다.
constructor(private x: string){}
}
const bar = new Bar('Hello');
console.log(bar) // Bar{x:'Hello'};

//private 선언된 bar.x는 클래스 내부에서만 참조가 가능하다.
console.log(bar.x) ; // Property 'x' is private and only accessible within class 'Bar'.

만일 생성자 파라미터에 접근 제하나자를 선언하지 않았을면 생성자 파라미터는 생성자 내부에서만 유효한 지역 변수가 되어 생ㅅ어자 외부에서 참조가 불가능하게 된다.

1
2
3
4
5
6
7
8
 class Foo {
//x는 생성자 내부에서만 유효한 지역 변수이다.
constructor(x:string){
console.log(x);
}
}
const foo = new Foo('Hello');
console.log(foo) //Foo {};

4.readonly 키워드

TypeScript는 readonly키워드를 사용할 수 있다. readonly가 선언된 클래스 프로퍼티는 선언시 또는 생성자 내부에서만 값을 할당 할 수 있다. 그 외의 경우에는 값을 할당할 수 없고 오직 읽기만 가능한 상태가 된다.이를 이용하여 상수의 선언의 선언에 이용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo {
private readonly MAX_LEN:number = 5;
private readonly MSG:string;

constructor(){
this.MSG = 'hello';
}
log(){
//readonly가 선언된 프로퍼티는 재할당이 금지된다.
this.MAX_LEN =10 // Cannot assign to 'MAX_LEN' because it is a constant or a read-only property.
this.MSG = 'hi'; //Cannot assign to 'MSG' because it is a constant or a read-only property.

console.log(`MAX_LEN : ${this.MAX_LEN}`) // MAX_LEN: 5
console.log(`MSG: ${this.MSG}`) MSG: 'hello';
}
}
new Foo().log();

5. static 키워드

ES 클래스 에서 static키워드는 클래스의 정적 메소드를 정의한다. 정적 메소드는 클래스의 인스턴스가 아닌 클래스의 이름으로 호출한다. 따라서 클래스의 인스턴스를 생성하지 않아도 호출 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Foo{
constructor(prop){
this.prop = prop;
}
static staticMethod(){
//정적 메소드는 this를 사용할 수 없다
//정적 메소드 내부에서 this는 클래스이 인스턴스가 아닌 클래스 자신을 가리킨다.
return 'staticMethod';
}
prototyprMethod(){
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키워드를 클래스 프로퍼티로 사용 할 수 있다. 정적 메소드와 마찬가지로 정적 클래스 프로퍼티는 인스턴스가 아닌 클래스 이름으로 호출하며 클래스의 인스턴스를 생성하지 않아도 호출할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Foo{
//생성된 인스턴스의 개수
static instanceCounter = 0;
constructor(){
//생성자가 호출될 때 마다 카운터를 1씩 증가 시킨다..
Foo.instanceCounter ++;
}
}
var foo1 = new Foo();
var foo2 = new Foo();

console.log(Foo.instanceCounter) //2;
console.log(foo2.instanceCounter) // error TS2339: Property 'instanceCounter' does not exist on type 'Foo'.

6. 추상 클래스

추상클래스(abstract class)는 하나 이상의 추상 메소드를 포함하며 일반 메소드도 포함 할 수 있다. 추상 메소드는 내용이 없이 메소드 이름과 타입만이 선언된 메소드를 말하며 선언할 때 abstract 키워드를 사용한다. 추상 클래스를 정의할 때는 abstract 키워드를 사용하며, 직접 인스턴스를 생성할 수 없고 상속만을 위해 사용된다. 추상 클래스를 상속한 클래스는 추상 클래스의 추상 메소드를 반드시 구형하여야한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
abstract class Animal{
//추상 메소드
abstract makeSound():void;
//일반 메소드
move():void{
console.log('move move')
}
}
//직접 인스턴스를 생성할 수 없다.
//new Animal();
// error TS2511: Cannot create an instance of the abstract class 'Animal'.

class Dog extends Animal{
//추상 클래스를 상속한 클래스는 추상 클래스의 추상 메소드를 반드시 구현 해야한다.
makeSound(){
console.log('hihi');
}
}
const dog = new Dog();
dog.makeSound() // hihi;
dog.move() // move move

인터 페이스는 모든 메소드가 추상 메소드이지만 추상클래스는 하나 이상의 추상 메소드와 일반 메소드를 포함 할 수 있다.