2024. 12. 21. 01:04ㆍProgramming Language/Node.js
▶클래스(Class)
클래스는 객체를 생성하기 위한 청사진이다.
속성과 메서드를 정의해서 사용할 수 있고 이 클래스를 사용해서 객체를 만들 수 있다.
클래스의 구성요소로는 필드, 생성자, 메서드가 있다.
▷필드
클래스가 가지는 데이터(속성)를 지칭하고 타입을 명시적으로 지정할 수 있다.
class ClassName {
field1 : string;
field2 : number;
. . . .
}
이렇게 클래스의 안에 인터페이스에서 속성 선언하듯 선언해주면 이걸 클래스에서는 필드라고 부른다.
▷생성자(Constructor)
클래스가 인스턴스를 생성할 때 호출되는 메서드로 필드의 초기화 작업을 수행하는 기능을 한다.
class ClassName {
field1 : string;
field2 : number;
constructor(field1 : string, field2 : number){
this.field1 = field1;
this.field2 = field2;
}
. . . .
}
이렇게 정의하고
const instClass = new ClassName("Hi", 123) //ClassName 타입 객체 생성
console.log(instClass.field1); // Hi 출력됨
으로 출력해보면 값을 확인할 수 있다.
▷메서드(Method)
클래스가 제공하는 기능을 정의한다.
this를 사용해서 클래스의 필드와 메서드에 접근해서 사용한다.
class ClassName {
field1 : string;
field2 : number;
constructor(field1 : string, field2 : number){
this.field1 = field1;
this.field2 = field2;
}
method1 (arg1 : string, arg2 : number){
return `arg1 : ${arg1}, arg2 : ${arg2}`;
}
method2 (arg1 : string, arg2 : number){
return `arg2 : ${arg2}, arg1 : ${arg1}`;
}
}
이렇게 내부에 선언해주면
const instClass = new ClassName("Hi", 123);
console.log(instClass.func1("Hello", 1234)); // arg1 : Hello , arg2 : 1234
console.log(instClass.func2("Hola", 4321)); // arg2 : 4321 , arg2 : Hola
와 같이 사용할 수 있게 된다.
▶접근제어자 (Access Modifiers)
클래스의 멤버(필드, 메서드)에 접근하는 범위를 제한하기 위해서 사용한다.
접근 제어자의 종류는 public, private, protected가 있다.
▷Public(기본값)
어디서나 접근이 가능한 접근제어자이다.
명시적으로 선언하지 않아도 기본적으로 public이다.
class ClassName {
field1 : string;
public field2 : number;
constructor(field1 : string, field2 : number){
this.field1 = field1;
this.field2 = field2;
}
method1 (arg1 : string, arg2 : number){
return `arg1 : ${arg1}, arg2 : ${arg2}`;
}
public method2 (arg1 : string, arg2 : number){
return `arg2 : ${arg2}, arg1 : ${arg1}`;
}
}
이렇게 붙이나 안붙이나 public으로 제한되어 있다.
▷Private
클래스 내부에서만 접근이 가능하다.
class ClassName {
private field1 : string;
field2 : number;
constructor(field1 : string, field2 : number){
this.field1 = field1;
this.field2 = field2;
}
private method1 (arg1 : string, arg2 : number){
return `arg1 : ${arg1}, arg2 : ${arg2}`;
}
method2 (arg1 : string, arg2 : number){
return `arg2 : ${arg2}, arg1 : ${arg1}`;
}
}
이렇게 private를 접근제어자로 설정한 멤버의 경우는
const instClass = new ClassName("Hello", 1234);
console.log(instClass.field1) // 접근 불가 에러
console.log(instClass.field2) // 접근 가능
▷Protected
private와 비슷하나 상속받은 클래스에서도 접근이 가능하다.
class Parent{
protected message : string;
constructor (message : string){
this.message = message
}
}
class Child extends Parent {
public showMessage() : void {
console.log(this.message); // 상속받은 클래스에서 접근이 가능하다
}
}
이렇게 상속을 한 경우에 자식 클래스에서 해당 필드에 접근이 가능해진다.
const child = new Child("Hello from Parent");
child.showMessage();
그러나 그냥 단독으로 message에는 접근할 수 없다.
console.log(child.message); // 에러 발생
추가적으로 클래스에서는 필드를 초기화한 후에 수정이 불가능한 읽기 전용(Readonly) 속성을 사용할 수 있다.
class ClassName {
readonly field1: string;
field2: number;
constructor(field1: string, field2: number) {
this.field1 = field1;
this.field2 = field2;
}
. . . .
}
이렇게 필드를 readonly로 선언해두면 변경이 불가능하고
const instClass = new ClassName("Hello", 1234);
instClass.field1 = "Change";
읽어 오는 기능한 사용이 가능하다.
console.log(instClass.field1); // Hello
▶ 단축 문법 : 생성자 파라미터 속성
타입스크립트에서는 생성자를 통해서 매개변수를 자동으로 클래스 필드로 선언하고 초기화하는 단축 문법을 사용할 수 있다.
class ClassName {
constructor (public field1 : string, private field2 : number) {}
public getField () : string {
return `field1 : ${this.field1}, field2 : ${this.field2}`
}
}
위와 같이 생성자의 매개변수를 받듯이 작성해준 다음에 접근제어자를 붙여주면 필드에 값을 초기화하는 구현부를 구현하지 않더라도 생성자를 통해서 필드를 생성하면서 값을 넣어준다.
만약 필드에 초기값이 필요하다면
constructor (public field1 : string = 'Hello ', private field2 : number = 0) {}
이렇게 값을 넣어주면서 생성자의 생성도 가능하다.
정의한 클래스를 사용하는 방법은 아래와 같다.
const instClass = new ClassName("Hello", 1234);
console.log(instClass.field1);
console.log(instClass.getField());
▶ 상속
클래스의 경우도 인스턴스처럼 상속이 가능하다
인스턴스도 이전에 생성한 인스턴스에서 상속하면 그 인스턴스의 속성을 가져다 사용할 수 있었다.
클래스의 경우도 비슷하다.
class ParentClassName {
constructor (public field1 : string, protected field2 : number) {}
public getField () : string {
return `field1 : ${this.field1}, field2 : ${this.field2}`
}
}
class ChildClassName extends ParentClassName {
public getField2 () : string {
return `field2 : ${this.field2}, field1 : ${this.field1}`
}
}
이렇게 자식 클래스의 경우는 생성자를 생성하지 않더라도 부모에게 상속받아 생성한 것 처럼 사용할 수 있다.
const instClass = new ChildClassName("Hello", 1234);
그리고 부모 클래스의 필드와 메서드를 상속받은 자식 클래스에서 사용도 가능하다
console.log(instClass.field1);
console.log(instClass.getField());
console.log(instClass.getField2());
▶ 정적 멤버(Static Members)
static이란 키워드를 사용하면 클래스 자체에 속하는 속성이나 메서드를 정의하고 이렇게 클래스 자체에 속하는 경우는 인스턴스를 생성하지 않더라도 호출이 가능해진다.
class StaticFieldClassName {
static FIELD: string = "Static Field";
static getField (arg : string) : string {
return `arg : ${arg}`
}
}
이렇게 static이란 키워드를 붙여주면
console.log(StaticFieldClassName.FIELD);
console.log(StaticFieldClassName.getField("Hello"));
이렇게 인스턴스를 생성하지않고 그냥 클래스명을 통해서 멤버와 메서드에 접근이 가능하다.
▶ 추상 클래스 (Abstract Class)
추상 클래스는 인스턴스를 생성할 수 없고 상속받은 클래스가 구현해야 하는 추상 메서드를 정의해두는 클래스이다.
추상 클래스를 생성하기 위해서는 abstract 키워드를 사용한다.
abstract class AbstractClassName {
abstract absMethod(): string;
}
이렇게 생성된 추상 클래스를 사용할때에는
class ChildClassName extends AbstractClassName {
absMethod(): string {
return 'extended abstract method';
}
}
이렇게 자식클래스로 가져와서 구현부를 정의해주면 된다.
자식 클래스의 경우는 추상 클래스를 상속하는 경우는 무조건 추상 클래스에 선언된 메서드를 정의해줘야만 하는 의무가 생긴다.
이렇게 추상 메서드에 선언된 메서드를 상속받는 클래스에서 정의하지 않으면 컴파일 에러를 발생시킨다.
상속받는 자식 클래스의 경우는 추상메서드에 선언된 메서드의 메서드명, 매개변수의 종류, 반환타입을 동일하게 적용해야 한다.
abstract class AbstractClassName {
abstract absMethod(message : string): string;
}
class ChildClassName extends AbstractClassName {
absMethod(message : string): string {
return 'extended abstract method';
}
}
매개변수의 경우는 반공변적(Contravariant)인 성격을 띄기 때문에 자식 메서드의 매개변수의 경우는 부모 메서드의 매개변수보다 더 넓은 타입을 받아들 일 수 있도록 구현해야 한다.
위 코드를 보면
abstract class AbstractClassName {
abstract absMethod(message : string): string;
}
class ChildClassName extends AbstractClassName {
absMethod(): string {
return 'extended abstract method';
}
}
이 경우는 에러를 발생하지 않는데 자식 메서드의 매개변수가 비어 있는 경우는 어떤 값도 처리하지 않아도 되는 더 넓은 의미로 간주되기 때문에 에러를 발생하지 않는다.
더 넓은 타입이란 의미는 매개변수의 갯수를 의미하는게 아니라 타입이 더 큰 범위의 타입이여야 한다는 의미로
abstract class AbstractClassName {
abstract absMethod(message : string): string;
}
class ChildClassName extends AbstractClassName {
absMethod(message : any): string {
return 'extended abstract method';
}
}
이렇게 자식 타입에서는 부모 타입을 포함한 개념의 타입을 사용해야만 사용이 가능하다.
'Programming Language > Node.js' 카테고리의 다른 글
TypeScript에 대한 간단한 정리 - 09. 함수 - 오버로딩(Overloading) (0) | 2024.12.20 |
---|---|
TypeScript에 대한 간단한 정리 - 08. 함수 - 명시적 this 타입 (1) | 2024.12.20 |
TypeScript에 대한 간단한 정리 - 07. 타입 별칭(Alias) (0) | 2024.12.20 |
TypeScript에 대한 간단한 정리 - 06. 인터페이스 - 인덱싱 가능 타입 , 확장(상속) (0) | 2024.12.19 |
TypeScript에 대한 간단한 정리 - 05. 인터페이스 - 기본 , 함수 타입 (0) | 2024.12.18 |