Skip to content

Latest commit

 

History

History
292 lines (222 loc) · 7.33 KB

File metadata and controls

292 lines (222 loc) · 7.33 KB

Objects 사용하기

목표

  1. 클래스는 무엇이고 왜 사용하는가?
  2. Classes & Instances
  3. Interfaces

1. 객체지향 프로그래밍이란?

간단히 말하자면 실제 세상에 있는 것들로 코딩을 하는 것입니다.

예를들어 쇼핑사이트에서 물품리스트, 제품, 쇼핑카트 등으로 데이터를 분류하고 객체를 만들어서 프로그래밍 하는 것을 말합니다.

Classes & Instances

  • 객체
    • 만들려고 하는 실제 코드입니다.
    • 클래스의 인스턴스입니다.
    • 클래스에 기반해서 객체를 생성하는 것은 객체 리터럴을 사용하는 것의 대안입니다.
  • 클래스
    • 객체의 청사진입니다.
    • 프로퍼티와 메소드를 작성해서 객체가 어떻게 사용될 것인지 정의합니다.
    • 클래스를 만들면 유사한 객체를 쉽게 만들 수 있습니다.

2. 실제 적용해보기

회사의 다양한 부서가 있다고 가정해보겠습니다.

class Department {
  // 변수 타입 설정
  name: string;

  // constructor
  constructor(n: string) {
    this.name = n;
  }
}

const accounting = new Department('Accounting');
console.log(accounting);

이미 알고있는 간단한 클래스 문법에 타입을 지정해주었습니다.

1. method에서 this사용하기

메소드를 생성하고 클래스안에 있는 변수를 사용하기 위해서는 this 키워드를 사용해야 합니다.

'use strict';
class Department {
  // constructor
  constructor(n) {
    this.name = n;
  }

  describe() {
    console.log('Department: ' + this.name);
  }
}
const accounting = new Department('Accounting');
accounting.describe();

2. method copy 했을 때 this 인자로 받기

인스턴스를 복사하려 할 때 this는 같이 복사되지 않습니다.

const accountingCopy = { describe: accounting.describe };

// log => Department: undefined
accountingCopy.describe();

따라서 클래스를 작성할 때 메소드에 this를 넣어줘야 합니다. this의 타입은 클래스 자신이 됩니다.

class Department {
  // 변수 타입 설정
  name: string;

  // constructor
  constructor(n: string) {
    this.name = n;
  }
  describe(this: Department) {
    console.log('Department: ' + this.name);
  }
}

const accounting = new Department('Accounting');

// constructor 변수 같이 설정해주기
const accountingCopy = { name: 'DUMMY', describe: accounting.describe };

// log => Department: DUMMY
accountingCopy.describe();

3. private, public 키워드

아래 코드를 바로 살펴봅시다.

class Department {
  // 변수 타입 설정
  name: string;
  employees: string[] = [];

  // constructor
  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);
  }
}

accounting.addEmployee('MJ');
accounting.addEmployee('KIM');

accounting.employees[2] = 'Kooks'; // 이렇게 설정하더라도 배열에 들어감

마지막 줄에서 배열의 index를 통해 새로운 값을 추가해주고 있습니다. 이 방식은 클래스 밖에서도 정의되지 않은 방법으로도 접근이 가능합니다. 이런 방식을 제한하고자 할때 private키워드를 사용합니다.

class Department {
  // 변수 타입 설정
  name: string;
  private employees: string[] = [];

...

이렇게 사용하면 클래스 바깥에서 클래스 내부에서 정의되지 않은 방법으로 접근할 수 없습니다.

private과 public 키워드는 TypeScript에서만 유용한 키워드 입니다. JavaScript에서는 존재하지 않는 문법입니다.

4. 빠른 초기화

아래 코드를 봅시다.

class Department {
  // 변수 타입 설정
  //   private id: string;
  //   private name: string;
  private employees: string[] = [];

  // constructor
  constructor(private id: string, public name: string) {
    // this.id = id;
    // 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);
  }
}

이전 처럼 변수를 만들고 type과 public또는 private를 설정해 줄 수 있지만, constructor에서 한번에 변수를 설정할 수 도 있습니다.

  constructor(private id: string, public name: string) {
    // this.id = id;
    // this.name = n;
  }

5. readonly 속성

readonly는 말 그대로 변수를 읽기만 가능하게 설정하는 키워드 입니다. 초변수를 초기화 할 때 사용하고, 이후에 이 변수를 변경하려고 하면 하면 에러가 발생합니다.

class Department {
  private employees: string[] = [];

  // constructor
  constructor(private readonly id: string, public name: string) {
      this.id = id + '1010';
  }
  describe(this: Department) {
    console.log(`Department (${this.id}): ${this.name}`);
  }
  addEmployee(employee: string) {
    this.id = 'd2' //  readonly 속성 때문에 에러
    this.employees.push(employee);
  }
  printEmployeeInformation() {
    console.log(this.employees.length);
    console.log(this.employees);
  }
}

6. 상속

위에서는 전체적인 부서에 관해 클래스를 작성했습니다. 실제 부서처럼 IT 부서 클래스를 만들고자 합니다. IT 부서는 전체 부서 클래스를 기반으로 만들어집니다. 이때 속성들을 가져오기 위해 상속이란 개념을 사용합니다.

  • Department Class
    • IT Department (sub class)
class ITDepartment extends Department{
}

서브 클래스에서 this 키워드를 사용하기 위해선 먼저 super을 호출해야 합니다.

// 1번 예시
class ITDepartment extends Department {
  admins: string[]; // 없어도 되지만 아래 this의 순서를 보기 위해서 만듬
  constructor(id: string, admins: string[]) {
    super(id, 'IT');
    this.admins = admins;
  }
}

// 2번 예시
class AccountingDepartment extends Department {
  constructor(id: string, private reports: string[]) {
    super(id, 'Accounting');
  }

  addReport(text: string) {
    this.reports.push(text);
  }

  printReports() {
    console.log(this.reports);
  }
}

const accounting = new ITDepartment('d1', ['MJ']);

7. 프로퍼티 덮어쓰기 & protected 수정자

private을 사용하면 그 클래스를 상속한 클래스에서도 접근이 불가합니다. 하지만 protected를 사용하면 private와 기능은 같지만 상속받은 클래스에서도 접근이 가능해집니다.

class Department {
  // 변수 타입 설정
  //   private id: string;
  //   private name: string;
  protected employees: string[] = [];
	...
}
    
class AccountingDepartment extends Department {
  constructor(id: string, private reports: string[]) {
    super(id, 'Accounting');
  }

  addEmployee(name: string) {
    if (name === 'MJ') return;
    this.employees.push(name);
  }

  addReport(text: string) {
    this.reports.push(text);
  }

  printReports() {
    console.log(this.reports);
  }
}