일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 배열
- sql
- 코테연습
- Medium
- LeetCode
- 파이썬
- Level1
- 리트코드
- CS
- C++
- 프로그래머스
- OS
- VUE
- javascript
- 동적계획법
- Level2
- 고득점Kit
- web
- Level3
- 웹프로그래밍
- dp
- typescript
- 카카오
- 자바스크립트
- 리액트
- react
- Doitvue.js입문
- 백준
- python
- 프로그래밍
- Today
- Total
[TypeScript] 클래스 본문
클래스
OOP?
Work with (real-life) Entities in your code
Class & Instnaces
- Objects : The things you work with in code (Instance of classes)
- Classes : blueprints for objects
- 객체를 정의
- 다수의 객체를 생성
Class 생성하기
class Department {
//class field
name:string;
//생성자 함수
constructor(n: string) {
this.name = n;
}
}
const accounting = new Department('Accounting');
console.log(accounting);
자바스크립트로 컴파일하기
"use strict";
class Department {
constructor(n) {
this.name = n;
}
}
const accounting = new Department('Accounting');
console.log(accounting);
//# sourceMappingURL=app.js.map
public, private
클래스 필드에 배열 요소를 추가해보자
class Department {
//class field
name:string;
employees:string[] = [];
//생성자 함수
constructor(n: string) {
this.name = n;
}
describe(this: Department) {
console.log('Department: ' + this.name);
}
addEmployee(employee: string) {
this.employees.push(employee);
}
printEmployeeInformation() {
console.log(this.employees.length);
console.log(this.employees);
}
}
이 경우 addEmployee
메소드를 이용해서 employees
에 접근해 값을 추가하는 것 뿐만아니라 외부에서도 employees
배열을 참조하며 변경할 수 있다는 문제가 발생한다.
accounting.addEmployee('Max');
accounting.addEmployee('Manu');
accounting.employees[2] = 'Anna'; //외부에서 참조할 수 있다는 문제 발생
(자바스크립트에는 public의 개념만 있고 private의 개념은 없기 때문에 타입스크립트 컴파일 도중에는 중단 에러를 발생시키지만 이를 자바스크립트로 컴파일하면 에러 없이 런타임을 수행할 수 있다.)
이 경우 private
키워드를 사용하여 클래스 내부에서만 해당 프로퍼티에 접근할 수 있도록 지정할 수 있다.
private employees:string[] = [];
이와 반대로 public
키워드를 이용하여 외부에서도 참조할 수 있는 프로퍼티를 만들 수 있다. 기본값은 public
으로 지정된다.
클래스 프로퍼티 초기화 축약
생성자 함수의 인자로 제어 제어자와 타입을 지정해주면 자동으로 동일한 프로퍼티가 생성된다.
class Department {
//class field
// private id: string;
// private name:string;
private employees:string[] = [];
//생성자 함수
constructor(private id: string, public name: string) {
// this.id = id;
// this.name = n;
}
describe(this: Department) {
console.log(`Department (${this.id}) : ${this.name}`);
}
읽기 전용
초기화 후에 변경되어서도 안되는 특정 필드가 있는 경우 readonly
를 추가할 수있다. 읽기 전용이므로 초기화 중에 한 번만 사용할 수 있다.
constructor(private readonly id: string, public name: string) {}
상속
각 인스턴스 마다 고유의 특정 속성과 메소드를 갖는 경우 상속을 이용해 구현할 수 있다.
class ITDepartment extends Department { //Department 클래스를 상속
admins: string[];
constructor(id: string, admins: string[]) {
super(id, 'IT'); // 부모 클래스 생성자 호출
this.admins = admins;
}
}
const it = new ITDepartment('d1', ['Max']);
it.addEmployee('Max');
it.addEmployee('Manu');
console.log(it);
it.describe();
protected
외부에서 변경이 불가능하지만 해당 클래스를 확장하는 모든 클래스에서도 사용 가능하게 하기 위해서는 protected
키워드를 사용할 수 있다.
class AccountingDepartment extends Department {
constructor(id: string, private reports: string[]) {
super(id, 'IT');
}
addEmployee(name: string) { //부모 메소드 오버라이드
if (name === 'Max') return;
this.employees.push(name);
}
addReport(text: string) {
this.reports.push(text);
}
printReports() {
console.log(this.reports);
}
}
Getter, Setter
Getter
값을 가지고 올 때 함수나 메소드를 실행하는 속성으로 private 속성에 접근할 수 있도록 해준다. get
키워드를 사용하며 반드시 값을 리턴해야한다.
class AccountingDepartment extends Department {
private lastReport: string;
get mostRecentReport() {
if(this.lastReport) {
return this.lastReport; //반드시 return 해야함
}
throw new Error("No report found");
}
// ...
}
메소드가 아닌 프로퍼티로 접근할 수 있다.
const accounting = new AccountingDepartment('d2', []);
accounting.addReport('Something went wrong ...');
console.log(`mostRecentReport : ${accounting.mostRecentReport}`); //메소드로 접근 x, 프로퍼티로 접근해야함
Setter
getter와 마찬가지로 private 변수의 값을 설정하는 역할을 하며 set
키워드를 사용한다.
class AccountingDepartment extends Department {
private lastReport: string;
set mostRecentReport(value: string) {
if (!value) {
throw new Error('Please pass in valid value!');
}
this.addReport(value);
}
// (...)
}
마찬가지로 프로퍼티로 접근해야한다.
accounting.mostRecentReport = 'Year End Report';
static property, method
클래스의 인스턴스에서 접근할 수 없는 속성과 메소드를 클래스에 추가할 때 사용한다.
class Department {
// (...)
static fiscalYear = 2020;
static createEmployee(name: string) {
return {
name,
};
}
//(...)
}
해당 메소드나 프로퍼티를 호출할 때에는 새 키워드 없이 직접 클래스에서 호출하므로 클래스를 그룹화 메커니즘으로 사용하는 것과 같다.
const employee1 = Department.createEmployee('Max');
console.log(employee1, Department.fiscalYear);
클래스 내부의 정적이 아닌 부분들에서 정적 속성에 접근할 수 없다. this
는 클래스를 기반으로 생성된 인스턴스를 참조하기 때문이다. 정적 속성은 인스턴스에서 유효하지 않다. 정적 속성과 정적 메소드의 전체적인 개념은 인스턴스와 분리되어 있기 때문이다.
constructor(private readonly id: string, public name: string) {
console.log(this.fiscalYear); // error
console.log(Department.fiscalYear); // no error
}
추상 클래스
특정 클래스를 사용하거나 확장시킬 때 특정 메소드를 구현하거나 재정의하도록 해야하는 경우 기본 클래스에 추상화 메소드의 기본형만 정의해놓고 해당 클래스를 상속하는 모든 자식 클래스에서 해당 메소드를 재정의해서 쓰도록 할 수 있다.
abstract class Department {
// (...)
abstract describe(this: Department): void;
}
추상 메소드가 하나라도 있으면 해당 클래스에 abstract
키워드를 붙여야한다.
자식 클래스에서는 해당 메소드를 무조건 재정의해야한다.
class ITDepartment extends Department {
// (...)
describe(): void {
console.log('IT Department - ID: ' + this.id);
}
}
따라서 추상 클래스는 일부 상위 클래스를 기반으로 하는 모든 클래스가 일부 공통 메소드 또는 속성을 공유하도록 하는 경우 사용할 수 있다.
추상클래스는 자체적으로 인스턴스화 할 수 없고 기본적으로 상속되어야하는 클래스가 된다.
singleton & private constructor
싱글톤 패턴이란 특정 클래스의 인스턴스를 정확하게 하나만 갖도록 하는 패턴으로 정적 메소드나 속성을 사용할 수 없거나 사용하지 않고자 하는 동시에 클래스를 기반으로 정확히 하나의 객체만 가질 수 있도록 하고자할 때 사용할 수 있다.
싱글톤 패턴을 구현하기 위해서는 private constructor
를 사용한다.
private constructor(id: string, private reports: string[]) {
super(id, 'IT');
this.lastReport = reports[0];
}
이 경우 클래스 내부에서만 생성자 함수에 접근할 수 있어진다.
클래스 내부에 정적 변수로 인스턴스를 만든 후 정적 메소드로 인스턴스 생성 메소드를 구현한다.
static getInstance() {
if(AccountingDepartment.instance) {
return this.instance
}
this.instance = new AccountingDepartment('d2', []);
return this.instance;
}
그렇기 때문에 AccountingDepartment
의 인스턴스는 정확히 한 개만 생성된다.
const accounting = AccountingDepartment.getInstance();
const accounting2 = AccountingDepartment.getInstance();
콘솔로그를 통해 accounting
와 accounting2
는 같은 인스턴스라는 것을 확인할 수 있다.
'Web > TypeScript' 카테고리의 다른 글
[TypeScript] 고급타입 (0) | 2022.08.24 |
---|---|
[TypeScript] 인터페이스 (0) | 2022.08.19 |
[TypeScript] TypeScript 컴파일러 (0) | 2022.08.12 |
[TypeScript] Literal Type, Type alias, void, 함수, Unknown, Never (0) | 2022.08.10 |
Enum, Any, Union (0) | 2022.08.04 |