클래스 (Class)
- 클래스는 객체를 생성하기 위한 하나의 청사진/템플릿 역할을 한다.
- ES6에서 도입된 문법이며, 생성자(constructor), 속성(properties), 메서드(methods)로 구성된다.
- TypeScript에서는 클래스 내부의 속성과 매개변수, 반환값 등에 명시적인 타입 지정이 가능하다.
1. 기본 문법
ts
// 클래스 선언
class Country {
name: string;
capital: string;
}
// 인스턴스 생성
let country = new Country();
// 인스턴스에 속성 값 직접 할당
country.name = "South Korea";
country.capital = "Seoul";
console.log(country); // Country { name: "South Korea", capital: "Seoul" }
ts
// 생성자(constructor) 활용
class Country {
name: string;
capital: string;
constructor(name: string, capital: string) {
// 생성자 내부에서 초기화
this.name = name;
this.capital = capital;
}
}
// 인스턴스 생성 시 값 전달
let country = new Country("South Korea", "Seoul");
console.log(country); // Country { name: "South Korea", capital: "Seoul" }
- 생성자(constructor) 를 활용하면 인스턴스 초기값을 한 번에 설정할 수 있다.
- 일일이 프로퍼티를 대입하지 않아도 되므로 코드가 간결해진다.
2. 클래스의 상속 (Inheritance)
extends
키워드를 사용하면 부모 클래스의 속성과 메서드를 상속 및 확장할 수 있다.super()
는 부모 클래스의 생성자를 호출한다.
ts
// 부모 클래스
class Continent {
continentName: string;
constructor(name: string) {
this.continentName = name;
}
getContinentName() {
return this.continentName;
}
}
// 자식 클래스
class Country extends Continent {
name: string;
capital: string;
constructor(continentName: string, name: string, capital: string) {
super(continentName); // 부모 생성자 호출
this.name = name;
this.capital = capital;
}
// 메서드 오버라이드
getInfo() {
return `${this.name}, ${this.capital}, ${this.getContinentName()}`;
}
}
// 인스턴스 생성
const country = new Country("Asia", "South Korea", "Seoul");
console.log(country.getInfo()); // South Korea, Seoul, Asia
- 상속의 장점: 중복 코드 최소화, 구조적 확장, 공통 로직 재사용에 유리하다.
3. 접근 제어자 (Access Modifiers)
제어자 | 설명 | 접근 가능 범위 |
---|---|---|
public | 어디서나 접근 가능 (기본값) | 클래스 내부, 외부 |
private / # | 해당 클래스 내부에서만 접근 가능 | 클래스 내부 |
protected | 해당 클래스 및 하위 클래스에서 접근 가능 | 내부 + 하위 클래스 |
ts
// 접근 제어자 예제
class Continent {
public continentName: string; // 어디서나 접근 가능
private population: number; // 클래스 내부에서만 접근 가능
constructor(name: string, population: number) {
this.continentName = name;
this.population = population;
}
// 내부에서 private 속성 접근 가능
getPopulation() {
return this.population;
}
}
class Country extends Continent {
name: string;
capital: string;
constructor(
continentName: string,
population: number,
name: string,
capital: string
) {
super(continentName, population);
this.name = name;
this.capital = capital;
}
getInfo() {
// private 속성은 접근 불가
// this.population;
return `${this.name}, ${this.capital}, ${this.continentName}`;
}
}
// 인스턴스 생성
const country = new Country("Asia", 4600000000, "South Korea", "Seoul");
console.log(country.getInfo()); // 접근 가능
console.log(country.getPopulation()); // 내부 메서드 통해 간접 접근
// console.log(country.population); Error
💡 TypeScript의 접근 제어자는 컴파일 타임에만 검사되며,
실제 JavaScript 런타임에서는 완전한 캡슐화가 되지 않는다. 런타임 레벨의 캡슐화를 원한다면 #(private field)
사용 권장.
4. 인터페이스 구현 (Implements)
implements
키워드를 사용하면 클래스가 특정 구조(인터페이스) 를 반드시 구현하도록 강제할 수 있다.
ts
// 대륙 인터페이스 정의
interface ContinentInterface {
getContinentName(): string;
}
// 인터페이스 구현 클래스
class Continent implements ContinentInterface {
protected continentName: string;
constructor(name: string) {
this.continentName = name;
}
getContinentName() {
return this.continentName;
}
}
// 국가 인터페이스 정의
interface CountryInterface {
capital: string;
getInfo(): string;
}
// 다중 상속 + 인터페이스 구현
class Country extends Continent implements CountryInterface {
#name: string; // private 필드
capital: string;
constructor(continentName: string, name: string, capital: string) {
super(continentName);
this.#name = name;
this.capital = capital;
}
getInfo() {
return `${this.#name}, ${this.capital}, ${this.getContinentName()}`;
}
}
const country = new Country("Asia", "South Korea", "Seoul");
console.log(country.getInfo()); // South Korea, Seoul, Asia
- 인터페이스를 통해 클래스의 일관된 구조를 유지할 수 있다.
다수의 클래스가 동일한 메서드 시그니처를 가질 수 있도록 강제한다.
5. 추상 클래스 (Abstract Class)
abstract
키워드를 사용해 선언된 클래스는 인스턴스화할 수 없고, 상속을 통해서만 사용 가능하다.
ts
// 추상 클래스 정의
abstract class AbstractCountry {
name: string;
capital: string;
constructor(name: string, capital: string) {
this.name = name;
this.capital = capital;
}
setup(): void {
console.log("setup complete");
}
// 추상 메서드
abstract displayInfo(): void;
}
// const myCountry = new AbstractCountry();
// Error: 추상 클래스는 인스턴스화 불가
// 하위 클래스에서 추상 메서드 구현
class MyCountry extends AbstractCountry {
displayInfo() {
console.log(`${this.name}, ${this.capital}`);
}
}
// 인스턴스 생성
const myCountry = new MyCountry("Germany", "Berlin");
myCountry.setup(); // setup complete
myCountry.displayInfo(); // Germany, Berlin
- 추상 클래스는 인스턴스를 만들 수 없다.
- 추상 클래스는
extends
키워드를 사용해 상속받는다. abstract
추상 메서드는 반드시 하위 클래스에서 구체적으로 구현해야 한다.
정리
개념 | 키워드 | 설명 |
---|---|---|
클래스 | class | 객체 생성 템플릿 |
생성자 | constructor | 인스턴스 초기화 메서드 |
상속 | extends , super | 부모 클래스 기능 재사용 |
접근 제어자 | public , private , protected | 접근 범위 제한 |
인터페이스 구현 | implements | 클래스가 따라야 할 구조 정의 |
추상 클래스 | abstract | 인스턴스 불가, 상속용 기본 설계 |