클래스란 여러가지 유사한 객체를 쉽게 생성하는, 객체의 청사진입니다.
Javascript에서는 ES6부터 지원하고 Typescript에서는 개발자가 만드는 하나의 타입입니다.
let user1 = {
name: 'user1'
age: 10
}
let user2 = {
name: 'user2'
age: 20
}
이 두 객체는 모두 name
과 age
라는 공통된 속성을 가지고 있습니다.
이렇게 모양이 유사한 객체는 하나씩 정의하기보다 아래와 같이 생성사 함수를 사용하는 것이 유리합니다.
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
생성자 함수와 다르지만 역할은 동일합니다.
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'
이제 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
을 정의 해주고나면 에러가 사라집니다.
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보다 많아야 작동하기 때문에 작동하지 않을 것입니다.
public 제어자는 클래스 안에 선언된 속성과 메서드를 어디서든 접근할 수 있게 합니다.
별도의 접근 제어자를 붙이지 않을 경우 기본으로 public으로 선언 됩니다.
class WaterPurifier {
waterAmount: number;
constructor (waterAmount: number) {
this.waterAmount = waterAmount;
}
public wash() {
this.waterAmount--;
if (this.waterAmount > 0) {
console.log('쪼르륵 쪼르륵');
}
}
}
어디서나 접근이 가능하기에 객체를 생성후 wash()
메소드를 생성해도 작동합니다.
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 제어자는 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.name
과 this.age
가 private로 정의 되어있기 때문입니다.
반면에 sayHi()
는 정상적으로 접근이 가능합니다.
User
클래스를 상속받았기에 protected 제어자로 선언된 sayHi()
는 접근이 가능합니다.
접근제어자 | 외부접근 | 자식클래스 접근 |
---|---|---|
public | O | O |
private | X | X |
protected | X | O |
타입스크립트의 클래스에 대해서 알아봤습니다.
읽어주셔서 감사합니다.