쉽게 시작하는 타입스크립트: 4 - 클래스

Bumgu·2024년 1월 23일
0
post-thumbnail

클래스란 여러가지 유사한 객체를 쉽게 생성하는, 객체의 청사진입니다.
Javascript에서는 ES6부터 지원하고 Typescript에서는 개발자가 만드는 하나의 타입입니다.

1. 클래스?

let user1 = {
	name: 'user1'
    age: 10
}
let user2 = {
	name: 'user2'
    age: 20
}

이 두 객체는 모두 nameage라는 공통된 속성을 가지고 있습니다.
이렇게 모양이 유사한 객체는 하나씩 정의하기보다 아래와 같이 생성사 함수를 사용하는 것이 유리합니다.

function User(name, age) {
	this.name = name;
    this.age = age;
}

let user1 = new User('user1', 10);
let user2 = new User('user2', 20);

위의 코드처럼 함수의 첫 글자를 대문자로 작성하면 생성자 함수라고 보는 것이 일반적인 관례입니다. 생성자 함수는 new라는 키워드르 붙여서 새로운 객체를 생성 할 수 있습니다.

이 생성자 함수를 클래스 문법으로 표현하면

class User {
	constructor(name,age) {
    	this.name = name;
	    this.age = age
    }
}

이렇습니다. 이 User클래스는 위에 나온 User생성자 함수와 다르지만 역할은 동일합니다.

2. 클래스의 상속

class Pserson {
	construcrtor(name, skill) {
    	this.name = name;
	    this.skill = skill;
	}
    sayHi() {
    	console.log('hi');
    }
}
class Developer extends Person {
	constructor(name, skill) {
		super(name, skill);
	}
	
	coding() {
		console.log('coding');
	}
}

위의 코드는 Person 클래스를 상속받은 Developer 클래스가 있습니다.
Developer 클래스의 생성자를 보면 super키워드를 사용했습니다. 이 코드는 자식 클래스 (Developer)에서 new키워드로 객체를 생성할 때 부모 클래스(Person)의 생성자를 호출하겠다는 뜻입니다.

let kelly = new Developer('kelly', 'typescript);
kelly.coding(); // 'coding'

Developer클래스로 생성한 객체를 생성하고 coding()를 호출하면 'coding'이 콘솔에 출력됩니다.
근데 여기서 부모 클래스의 프로퍼티를 호출 할 수 있습니다.

kelly.sayHi() // 'hi'

3. 타입스크립트의 클래스

이제 ES6의 기본 클래스 문법을 배웠으니, 클래스에 타입을 정의 하는 방법을 보겠습니다.

class Chatgpt {
	constructor(name: string) {
		this.name = name;
	}
	sum(a: number, b: number): number {
		return a+ b;
	}
}

위의 ES6문법과 크게 다른부분은 없지만, 생성자의 파라미터에 string타입을 정의했고,
sum() 메소드의 파라미터와 반환타입 모두 number로 정의 했습니다.
기존에 알고있던 함수의 타입정의와 다르지 않습니다.
하지만 이 코드를 타입스크립트 파일에서 작성해보면 에러가 발생합니다

이유는 타입스크립트로 클래스를 작성할 때는 생성자 메서드에서 사용될 클래스 프로퍼티들을 미리 정의해주어야 하기 때문입니다.

class Chatgpt {
    name: string;
	constructor(name: string) {
		this.name = name;
	}
	sum(a: number, b: number): number {
		return a+ b;
	}
}

name을 정의 해주고나면 에러가 사라집니다.

4. 접근 제어자

class WaterPurifier {
  waterAmount: number;

  constructor (waterAmount: number) {
    this.waterAmount = waterAmount;
  }

  wash() {
    this.waterAmount--;
    if (this.waterAmount > 0) {
      console.log('쪼르륵 쪼르륵');
    }
  }
}

let purifier = new WaterPurifier(10);

정수기 WaterPurifier클래스가 있고 물의 양인 waterAmount 프로퍼티가 있습니다.
만약 waterAmount가 0보다 많아야 정수기가 작동하고, wash()메소드를 호출하면 waterAmount가 1씩 줄어들고 0이 되면 작동하지 않겠죠.

purifier.wash(); // 쪼르륵 쪼르륵

객체를 생성할 때 waterAmount의 값을 10을 줬기 때문에 작동합니다.
하지만 만약 누가 접근해서 waterAmount의 값을 0으로 바꾼다면 어떻게 될까요?

purifier.waterAmount = 0;

0보다 많아야 작동하기 때문에 작동하지 않을 것입니다.

4-1. 접근 제어자 : public, private, protected

public

public 제어자는 클래스 안에 선언된 속성과 메서드를 어디서든 접근할 수 있게 합니다.
별도의 접근 제어자를 붙이지 않을 경우 기본으로 public으로 선언 됩니다.

class WaterPurifier {
  waterAmount: number;

  constructor (waterAmount: number) {
    this.waterAmount = waterAmount;
  }

 public wash() {
    this.waterAmount--;
    if (this.waterAmount > 0) {
      console.log('쪼르륵 쪼르륵');
    }
  }
}

어디서나 접근이 가능하기에 객체를 생성후 wash()메소드를 생성해도 작동합니다.

private

private 제어자는 클래스 코드 외부에서 클래스의 속성과 메서드를 접근할 수 없습니다.
public과는 반대되는 개념으로 클래스 안 로직을 외부 세상에서 단절해 보호할 때 주로 사용합니다.

class User {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  private sayHi() {
    console.log('HI!!')
  }
}

모든 속성과 메소드가 private로 선언되었습니다.
이후 객체를 생성해보겠습니다.

let kelly = new User('kelly', 20);
console.log(kelly.name)


에러가 발생했습니다. 이 에러는 클래스의 name 속성이 private로 정의 되어있는데, 외부에서 해당 속성을 사용하려고 해서 발생했습니다.

이처럼 private 접근 제어자를 사용해 클래스 외부에서 속성과 메소드가 사용되는것을 방지 할 수 있습니다.

맨 위에서 했던 정수기 문제를 private 제어자를 통해 보완 할 수 있습니다.
위에서 했던 정수기 문제를 접근 제어자를 이용해 보완해보겠습니다.

class WaterPurifier {
  waterAmount: number;

  constructor (waterAmount: number) {
    this.waterAmount = waterAmount;
  }

 public wash() {
    this.waterAmount--;
    if (this.waterAmount > 0) {
      console.log('쪼르륵 쪼르륵');
    }
  }
}

waterAmount는 외부에서 맘대로 접근하면 안되는 속성이기 때문에 waterAmount에 pirvate 접근 제어자를 붙여주면 외부에서 값을 맘대로 조정해 정수기가 작동하지 않는 일은 없을 것 입니다.

class WaterPurifier {
	private waterAmount: number;
}

protected

protected 제어자는 private와 비슷하면서 다릅니다.
protected는 클래스 코드 외부에서 사용할 수 없지만, 상속받은 클래스에서는 사용이 가능합니다.

class User {
  private name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  protected sayHi(): void {
    console.log('HI!!')
  }
}

class GameUser extends User {
  constructor(name: string, age: number) {
    super(name: string, age: number);
    this.sayHi();
  }

	game(): void {
    	console.log(`${this.name} playing game ${this.age}`)
	}
}

name : private
age : private
sayHi() : protected
당연하게도 에러가 발생합니다.

자식 클래스인 GameUser의 메서드에서 에러가 발생합니다.
this.namethis.age가 private로 정의 되어있기 때문입니다.
반면에 sayHi()는 정상적으로 접근이 가능합니다.

업로드중..
User클래스를 상속받았기에 protected 제어자로 선언된 sayHi()는 접근이 가능합니다.

4-2. public, private, protected 차이

접근제어자외부접근자식클래스 접근
publicOO
privateXX
protectedXO

타입스크립트의 클래스에 대해서 알아봤습니다.
읽어주셔서 감사합니다.

profile
Software VS Me

0개의 댓글