클래스란
- 클래스는 객체의 청사진입니다.
- 클래스를 기반으로 하는 객체를 쉽게 만들 수 있으려면 어떤 메서드가 필요한지 정의할 수 있기 때문에 이를 클래스 내의 인스턴스라고 부릅니다. 따라서 객체는 클래스 내의 인스턴스입니다.
- 클래스를 기반으로 하면 동일한 구조, 동일한 클래스를 기반으로 하는 동일한 메서드로 여러 객체를 빠르게 복제할 수 있습니다.
- 클래스는 객체의 형태, 포함해야 할 속성과 메서드를 정의하는 데 도움이 되며 객체에 저장된 정확한 데이터 세부 정보만 다를 뿐입니다.
- 여러 사람들을 객체로 사용하여 표현하고자 한다면 사람들은 각각 이름과 나이가 다르지만 일반적인 구조는 같은 것입니다.
클래스 만들기
app.ts
class Department {
name: string;
constructor(n: string) {
this.name = n;
}
}
const accounting = new Department('Accounting');
console.log(accounting);
기본적인 클래스를 만드는 코드입니다.
Department(부서) 클래스를 열어 그 필드 안에 이름의 타입을 배정하고 생성자 함수를 통해 그 이름을 인수로 받았습니다.
app.js
"use strict";
class Department {
constructor(n) {
this.name = n;
}
}
const accounting = new Department('Accounting');
console.log(accounting);
//# sourceMappingURL=app.js.map
위 코드를 자바스크립트로 컴파일하면 이렇게 번역되며 약간 다르지만 매우 비슷한 형태를 띠고 있습니다.
지금까진 es6 자바스크립트로 컴파일해 왔고 세팅은 아래와 같습니다.
tsconfig.json
{
"compilerOptions": {
/* Basic Options */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": [
"dom",
"es6",
"dom.iterable",
"scripthost"
],
...
}
이를 es5 자바스크립트로 컴파일하기 위해 target을 "es5"로 바꾸고 lib과 관련된 내용을 모두 주석처리 해줍니다.
target은 어떤 버전으로 컴파일을 할 것인지 설정하는 것이고 lib은 타입스크립트가 이해할 수 있는 식별자를 설정하는 것입니다.
tsconfig.json
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "lib": [
// "dom",
// "es6",
// "dom.iterable",
// "scripthost"
// ],
...
}
위의 설정으로 자바스크립트로 컴파일하면 생성자 함수가 사라지고 그 함수가 반환문이 생겼습니다.
코드의 차이는 있지만 모두 근본적으로 자바스크립트에서 생성자 함수를 만드는 게 가능했습니다.
app.js
"use strict";
var Department = (function () {
function Department(n) {
this.name = n;
}
return Department;
}());
var accounting = new Department('Accounting');
console.log(accounting);
//# sourceMappingURL=app.js.map
자바스크립트가 최신화되고 타입스크립트가 생기면서 코드가 간결해지긴 했지만 이 클래스 개념은 오래전부터 사용되었던 걸 나타냅니다.
this 키워드
app.ts
class Department {
name: string;
constructor(n: string) {
this.name = n;
}
// 메소드
describe() {
console.log('Department: ' + this.name)
}
}
const accounting = new Department('Accounting');
accounting.describe(); // Department: Accounting
const accountingCopy = { describe: accounting.describe};
accountingCopy.describe(); // Department: undefined
위의 코드를 메서드를 생성하여 다르게 표현했습니다.
그러나 카피본을 만들고 그 메서드를 참조하게 했지만 name을 불러오지 못하고 undefined가 뜨게 되었습니다.
이는 accountingCopy 객체의 name에 접근하게 설정되어 있기 때문입니다.
app.ts
class Department {
name: string;
constructor(n: string) {
this.name = n;
}
describe(this: Department) { // 매개변수 추가
console.log('Department: ' + this.name)
}
}
const accounting = new Department('Accounting');
accounting.describe(); // Department: Accounting
const accountingCopy = { name: 'Marketing', describe: accounting.describe}; // name 속성 추가
accountingCopy.describe(); // Department: Marketing
이렇게 메서드에 this를 매개변수로 추가하고 복제에 name 속성을 추가하여 해결할 수 있었습니다.
private 수정자
private의 의미는 클래스, 즉, 생성된 객체 내부에서만 접근할 수 있는 속성이 되었다는 것을 의미합니다.
따라서 부서 클래스 내의 어떤 메서드로든 접근할 수 있지만, 다르게는 접근할 수 없게 됩니다.
app.ts
class Department {
public name: string;
private employees: string[] = []; // private 액세스 수정자
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)
}
}
const accounting = new Department('Accounting');
accounting.addEmployee('KIM');
accounting.addEmployee('PARK');
accounting.employees[2] = 'SON'; // 에러
accounting.name = 'Marketing'; // 에러 아님
위의 예시를 보면 private가 없었다면 두 방법 모두 employees에 접근할 수 있었지만 private로 선언했기에 메서드로는 접근할 수 있지만 두 번째 방법으로는 접근할 수 없습니다.
이와 다르게 쓰지 않아도 기본으로 설정된 public이 있으며 이는 외부에서도 접근할 수 있다는 것입니다.
이는 자바스크립트에서는 잡아줄 수 없는 기능이기에 타입스크립트에서만 지원하며 컴파일 에러는 발생하나 런타임 에러는 발생하지 않게 됩니다.
자바스크립트는 모두 public으로만 판단하고 넘어가게 됩니다.
이중 초기화 방지
app.ts
class Department {
// private id: string;
// public name: string;
private employees: string[] = [];
constructor(private id: string, public name: string) { // 여기
this.id;
this.name;
}
describe(this: Department) {
console.log(`Department (${this.id}): ${this.name}`);
}
}
생성자 함수에 매개 변수로 위의 선언된 속성들을 가져와 이중 초기화를 막으며 코드를 간결하게 할 수 있습니다.
readonly 속성
app.ts
class Department {
private employees: string[] = [];
// 여기
constructor(private readonly id: string, public name: string) {
this.id;
this.name;
}
describe(this: Department) {
console.log(`Department (${this.id}): ${this.name}`);
}
addEmployee(employee: string) {
this.id = 'A2'; // 에러
this.employees.push(employee)
}
printEmployeeInformation() {
console.log(this.employees.length);
console.log(this.employees)
}
}
readonly는 특정 속성이 초기화되고 나면 이후에는 변경되어서는 안 된다는 점을 명확히 할 수 있습니다.
상속
고유의 특정 속성과 메서드를 갖는 클래스도 있는데 그때 상속이 유용합니다.
app.ts
class ITDepartment extends Department {
constructor (id: string, public admins: string[]) {
super(id, 'IT');
this.admins = admins;
}
}
const newIT = new ITDepartment('B1', ['LEE']);
super는 기본 클래스의 생성자를 호출하며 다음 작업을 수행하기 전에 항상 먼저 호출해야 합니다.
protected 수정자
app.ts
class Department {
private employees: string[] = [];
// protected employees: string[] = [];
constructor(private readonly id: string, public name: string) {
this.id;
this.name;
}
describe(this: Department) {
console.log(`Department (${this.id}): ${this.name}`);
}
addEmployee(employee: string) {
this.employees.push(employee)
}
printEmployeeInformation() {
console.log(this.employees.length);
console.log(this.employees)
}
}
class AccountingDepartment extends Department {
constructor(id: string, private reports: string[]) {
super(id, 'Accouting');
}
addEmployee(name: string) {
if( name === 'KIM') {
return;
}
this.employees.push(name); // 에러
}
}
private 속성은 정의된 클래스 내에서만 접근 가능하며 해당 클래스로부터 상속받는 클래스에서는 불가능합니다.
상속받는 클래스에서 접근할 수 있도록 하면서 외부에서 변경 불가능한 속성으로 만들고자 한다면 주석 처리 된 것처럼 private를 protected로 바꾸면 됩니다.
'TYPESCRIPT' 카테고리의 다른 글
인터페이스 (7) | 2023.03.23 |
---|---|
클래스 2 (6) | 2023.03.21 |
타입스크립트 컴파일러 (7) | 2023.03.17 |
타입스크립트 기초 2 (6) | 2023.03.13 |
타입스크립트 기초 1 (7) | 2023.03.09 |