클래스(Class)
클래스는 객체를 생성하기 위한 템플릿으로서,
해당 클래스로부터 생성된 객체를 인스턴스라고 한다.
클래스를 사용하면 데이터와 해당 데이터에 대한 메서드를 하나로 묶어서
사용자 정의 타입을 생성할 수 있다.
클래스 구성요소(Members)
- 필드(field)
- 생성자(constructor)
- 메소드(method)
📝 클래스 선언
클래스 몸체에 클래스 프로퍼티를 사전 선언
class 클래스명 {
[private | protected | public] property name[?]: property type[...]
}
class 클래스명 {
멤버필드명: 타입;
constructor(매개변수명: 타입) {
this.멤버필드명 = 매개변수명;
}
메소드명(this: 클래스명) {
//this 사용
}
}
new 클래스명(타입에 맞는 값);
필드 (field)
- 클래스 내부 변수. 보통 필드 보다는 '멤버 변수'로 많이 부른다.
- 클래스 내부에서 타입과 함께 선언.
- 필드는 클래스 내에서 생성자에 의해 반드시 초기화되어야 한다.
● ! 옵션 : 필드 이름 뒤에 !를 붙여주면 undefined로 자동 초기화된다.
따라서 생성자에서 초기화 안해줘도 에러 안난다.
● readonly 옵션 : 필드 이름 앞에 readonly 옵션을 넣어주면 해당 필드는 인스턴스 생성 이후 변경 불가.
즉, 생성자 안에서만 초기화 가능.
class Point {
x: number; // Error - 생성자 초기화 안해줌
y!: number; // ! 옵션은 undefined로 자동 초기화
readonly z: number // 인스턴스 생성 이후 변경 불가
}
생성자 (constructor)
- 필드 초기화 함수로, 함수명은 constructor로 고정된다.
- new 연산자와 함께 호출되면서 새로운 객체를 생성한다. 이때 생성된 객체를 '인스턴스'
- 클래스 내애서 생성자는 오직 한개만 존재할 수 있다.
- this 는 클래스 자신을 말한다.
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`안녕하세요! 제 이름은 ${this.name}이고, 나이는 ${this.age}살입니다.`);
}
}
const person = new Person('Sohyun', 29);
person.sayHello();
메소드 (method)
- 클래스 내 생성자 이외의 함수들
- 함수 선언 시 'function'이 생략된 것에 주의
class Pdoint {
x: number;
y: number;
// 생성자
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
// 메소드
distance(): number {
return Math.pow(this.x - this.y, 2);
}
}
인스턴스 생성
클래스는 데이터와 이를 조작하는 메서드 등을 하나로 뭉쳐놓은 추상화된 '몸체'다.
이는 아직 객체라 할수 없으며 객체화를 위해선 인스턴스 생성이 필요하다.
인스턴스 생성은 new + 클래스명을 코드 하단에 입력하면 된다.
클래스 입력 후 가장 하단에서 불러와야 인스턴스가 생성된다. (잠정적 데드존)
new 클래스명(); 을 통해,
new 클래스명('매개변수');
클래스 내부의 코드들을 호출하고 생성자(constructor)를 실행 및 초기화한다.
class 클래스명 {
멤버필드명: 타입;
constructor(매개변수명: 타입) {
this.멤버필드명 = 매개변수명;
}
}
new 클래스명(타입에 맞는 값);
캡슐화
- Private Field (#필드명)
- Accessors (접근자) : Getter & Setter
class Fruit {
#name: string;
#price: number;
constructor(name:string, price:number){
this.#name = name;
this.#price = price;
}
set Name(name:string) { this.#name = name; }
set Price(price:number) { this.#price = price; }
get Name():string { return this.#name; }
get Price():number { return this.#price; }
}
let fruit: Fruit = new Fruit("딸기", "5000");
fruit.Name = "멜론"; // fruit.Name("멜론");
console.log(fruit.Name); // console.log(fruit.Name());
// '#name' 속성은 프라이빗 식별자를 포함하기 때문에 'Fruit' 클래스 외부에서 액세스할 수 없습니다.ts(18013)
// console.log(fruit.#name);
Private Field (#필드명)
ES6부터 클래스에 프라이빗 필드를 설정할 수 있다.
앞에 #을 붙이면 설정이 가능한데 이는 클래스의 외부에서 사용뿐만 아니라 탐지가 불가능하게 된다.
이 뿐만 아니라 프라이빗 필드를 사용하면
클래스를 상속할 때 해당 필드에 값이 덮어씌워지는 것을 막을 수 있다.
프라이빗 필드는 클래스 내의 프로퍼티를 은닉하고 캡슐화하기 위해 존재한다.
# 접두사 : 변수를 선언할 때 #를 붙이면 해당 변수가 프라이빗 필드가 됩니다.
완전한 프라이버시 : 클래스 외부에서는 이 필드에 절대 접근할 수 없으며,
심지어 클래스 인스턴스를 통해서도 접근이 불가능합니다.
이 접근은 클래스 내부에서만 가능합니다.
접근 제한 : 이 필드에 접근하거나 수정하려면, 클래스 내에서만 가능합니다.
외부에서 접근하려고 하면 컴파일러가 오류를 발생시킵니다.
class MyClass {
#privateField: string;
constructor(value: string) {
this.#privateField = value;
}
public getPrivateField() {
return this.#privateField;
}
}
const myInstance = new MyClass("Hello");
// console.log(myInstance.#privateField); // 오류 발생: '#privateField'은(는) private 필드이므로 클래스 외부에서 접근할 수 없습니다.
console.log(myInstance.getPrivateField()); // "Hello"
Accessors (접근자) : Getter & Setter
- 비공개로 설정하려는 속성은 private로 설정하고, 속성 값을 읽고 수정하는 getter/setter 함수를 사용한다.
- class의 속성에 직접 접근하는 것을 막고,
getter / setter 함수를 사용해 값을 받아오거나 수정한다.
- 속성에 직접 접근해 수정하면 데이터 무결성이 깨질 수 있다. (캡슐화 권장)
- 각 객체의 멤버에 접근하는 방법을 세밀하게 제어할 수 있다.
- 괄호를 적을 필요 없이 get함수와 set함수는 일반 변수처럼 이용
📝 게터(getter) 형태 - 값 반환
// ▶정의
get 함수명() {
return this.property명;
}
// ▶사용
// this → 현재 class를 가리키는 참조 변수
// super → 부모 class를 가리키는 참조 변수
this.함수명;
super.함수명;
📝 세터(setter) 형태 - 값 변경
// ▶정의
set 함수명(매개변수명: 타입) {
// property 수정 처리
}
// ▶사용
this.함수명 = value;
super.함수명 = value;
사용예시
만약 프로퍼티에 제약조건을 적용한다고 가정하자.
이 때, Setter를 통해 인스턴스 초기화 전에 조건을 걸 수 있다.
또, private 프로퍼티에 접근해야 하는 경우, Getter 함수를 통해 이를 연동해야 한다.
* _[변수명] 은, private 프로퍼티를 정의하는 컨벤션으로 '_'(언더스코어)를 앞에 붙여준다.
class Employee {
private _fullName: string;
// Getter : private 프로퍼티 접근
get fullName(): string {
return this._fullName;
}
// Setter : name 길이가 10 미만인 경우만, _fullName 프로퍼티에 할당
set fullName(newName: string) {
if (newName && newName.length > 10) {
throw new Error("fullName has a max length of ten");
}
this._fullName = newName;
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
console.log(employee.fullName);
}
🏷️ 접근제어자
해당 접근제어자를 사용한 변수에 접근할 수 있는 곳은 위와 같다.
선언한 클래스 | 상속받은 클래스 | 인스턴스 | |
public | ⭕ | ⭕ | ⭕ |
protected | ⭕ | ⭕ | ❌ |
private | ⭕ | ❌ | ❌ |
🏷️ this와 super의 차이
this
- 현재 class를 가리키는 참조 변수입니다.
- 현재 class 및 부모 class의 속성 및 method에 접근할 수 있습니다.
단, 부모 Class의 private 접근 제한자를 가진 속성 및 method는 사용할 수 없습니다.
super
- 부모 class를 가리키는 참조 변수입니다.
- public 또는 protected로 상속받은 method만을 사용할 수 있습니다. 직접 접근이 불가능합니다.
그래서 getter나 setter를 이용하여 속성을 제어해야 합니다.
- 사용 이유?
① 자식, 부모 class의 속성 및 method 구분을 하는 데 사용합니다.
② overrding 할 때 편하게 하기 위해서 사용 가능합니다.
'📌 Front End > └ TypeScript' 카테고리의 다른 글
[TypeScript] 타입스크립트 클래스 · 객체 지향 문법 총 정리 (0) | 2024.07.31 |
---|---|
[TypeScript] 열거형(Enum)타입 (0) | 2024.07.31 |
[TypeScript] 타입스크립트 예외 처리 Errors (Try, Catch, Finally, Throw) (0) | 2024.07.26 |
[TypeScript] 타입스크립트 함수(Function) (1) | 2024.07.26 |
[TypeScript] 타입 별칭(Type Alias), 인터섹션 타입 (Intersection Type), 맵드 타입(Mapped type) (1) | 2024.07.22 |