class Student {
// 필드
name;
grade;
age;
// 생성자
constructor(name, grade, age) {
this.name = name;
this.grade = grade;
this.age = age;
}
// 메서드
// 원래 객체 생성 시 선언하던 방식과 같은 방식으로 하면 됨.
study() {
console.log("열심히 공부함!");
}
introduce() {
// 이 클래스를 통해 생성한 객체의 프로퍼티를 불러옴.
console.log(`안녕하세요! ${this.name}입니다.`);
}
}
// 클래스를 통한 객체 생성 => 인스턴스
let studentB = new Student("정지수", "A+", 26);
console.log(studentB);
studentB.study();
studentB.introduce();
자바스크립트에서 클래스를 생성하는 방법을 보면, 필드를 선언하고 해당 객체의 필드 값들을 초기화하기 위해 생성자 constructor
를 사용한다.
메서드는 객체를 생성할 때 선언하는 방식과 동일하게 선언하면 된다.
// 상속을 활용한 클래스 확장
class StudentDeveloper extends Student {
// 필드
favoriteSkill;
// 생성자
// 매개변수는 지우면 안됨(!)
constructor(name, grade, age, favoriteSkill) {
super(name, grade, age); // 부모 클래스의 생성자 호출
this.favoriteSkill = favoriteSkill;
}
// 메서드
programming() {
console.log(`${this.favoriteSkill}로 프로그래밍함.`);
}
}
위와 같이 extends 키워드를 활용한 클래스 확장도 가능하다. 이 때 생성자에서 매개변수는 슈퍼 타입에서 선언한 매개변수도 모두 넣어줘야 한다.
또한 super()를 사용해 부모 클래스의 생성자를 호출해, 해당 매개변수들을 초기화한다. 자바스크립트에서는 이를 생략한다고 큰 문제가 생기진 않는다.
class Employee {
// 필드
// 타입을 할당해주지 않으면 any 타입이 할당됨.
// 따라서 기본값을 할당해주거나, 생성자를 통해 초기화해주거나!
name: string;
age: number;
position: string;
// 생성자
constructor(name: string, age: number, position: string) {
this.name = name;
this.age = age;
this.position = position;
}
// 메서드
work() {
console.log("일하기");
}
}
// 클래스를 통한 객체 생성
const employeeB = new Employee("정지수", 26, "개발자");
console.log(employeeB);
타입스크립트에서 클래스를 선언하는 방식도 자바스크립트와 비슷하게, 필드와 메서드를 선언해주면 된다.
하지만 각 필드의 타입을 선언해주는 것만으로는 에러가 해결되지 않는다. 이는 생성자 constructor
를 통해 값을 초기화해주어야 한다.
// 클래스의 확장
// TS에서는 super()를 사용하지 않으면 에러가 발생! (JS에서는 큰 문제가 아니었음.)
class ExecutiveOfficer extends Employee {
// 필드
officeNumber: number;
// 생성자
constructor(name: string, age: number, position: string, officeNumber: number) {
super(name, age, position);
this.officeNumber = officeNumber;
}
}
클래스를 확장하는 방식도 비슷하다.
여기서 주의해야 할 점은 생성자에서 부모 클래스의 생성자를 호출하는 것이 필수라는 점이다. 이 과정을 진행하지 않는다면 상속하는 것이 의미가 없기 때문이다.
- 클래스를 만들 때 특정 필드나 메서드에 접근할 수 있는 범위를 설정.
public
/private
/protected
이렇게 세 가지가 존재.- 기본 값은 public이다.
class Employee {
// 필드
public name: string;
private age: number;
protected position: string;
// 생성자
constructor(name: string, age: number, position: string) {
this.name = name;
this.age = age;
this.position = position;
}
// 메서드
work() {
console.log("일하기");
}
}
const employee = new Employee("정지수", 26, "developer");
// 이와 같이 프로퍼티 값 수정이 가능하나, private 키워드를 사용헸기 때문에 접근이 불가능.
// employee.age = 30;
1️⃣ private 키워드를 사용하면 클래스 내에서만 접근이 가능하고, 밖에서는 접근이 불가능하다. 그래서 위 코드에서처럼 private으로 선언한 필드인 age를 클래스 밖에서 접근하려고 하면 에러가 나는 것이다.
2️⃣ protected 키워드를 사용하면 해당 클래스와 그 클래스를 상속한 클래스 내에서만 접근이 가능하고, 밖에서는 접근이 불가능하다.
3️⃣ 생성자의 매개변수에서 접근 제어자를 사용하면 필드 선언과 생성자를 통한 기본값 초기화는 필요 없어진다. 생성자에서의 선언을 통해 알아서 기본값 초기화까지 해주기 때문!
- 인터페이스는 클래스의 설계도 느낌.
- implements 키워드를 사용해서 인터페이스를 구현하는 클래스를 선언.
interface CharacterInterface {
name: string;
moveSpeed: number;
move(): void;
}
// Character 클래스는 CharacterInterface를 구현한다.
class Character implements CharacterInterface {
constructor(public name: string, public moveSpeed: number) {}
move(): void {
console.log(`${this.moveSpeed} 속도로 이동.`);
}
}
이렇게 인터페이스로 설계도까지 만들면서 구현할 일이 자주 있지는 않지만, 알아두면 도움이 된다고 함!
추가로 interface로 구현한 필드들은 무조건 public이어야 함!