클래스와 인스턴스
클래스
- 어떤 사물의 공통 속성을 모아 정의한 추상적인 개념
- 객체를 만들기 위한 "설계도" 또는 "템플릿"
- ES6 도입, 기존 프로토타입 기반 상속을 보다 명확하고 쉽게 사용할 수 있게 해줌
인스턴스
- 클래스의 속성을 지니는 객체
클래스의 특징
constructor, 인스턴스 메서드, static
class Person {
// 생성자 메서드
constructor(name) {
this.name = name;
}
// 인스턴스 메서드
sayHello() {
console.log(`안녕하세요, ${this.name}입니다.`);
}
// 정적 메서드
static create(name) {
return new Person(name);
}
}
// 사용 예시
const person1 = new Person("김철수"); // 생성자 메서드 사용
person1.sayHello(); // 인스턴스 메서드 사용 (출력: 안녕하세요, 김철수입니다.)
const person2 = Person.create("홍길동"); // 정적 메서드 사용
■ constructor(생성자 메서드)
- 객체를 생성할 때 자동으로 호출
- 클래스의 초기 속성을 설정하는데 사용
- 클래스 본문에서는 'function' 키워드를 생략하더라도 모두 메서드로 인식
■ 인스턴스 메서드(프로토타입 메서드)
- 클래스의 prototype 내부에 정의된 메서드
- 인스턴스가 직접 호출 가능하며 인스턴스의 프로퍼티를 참조하고 조작하는데 사용
- 해당 메서드는 클래스의 모든 인스턴스가 공유하여 효율적인 메모리 사용이 가능하다.
■ static(정적 메서드)
- 클래스(생성자 함수) 에 직접 정의한 메서드
- 인스턴스가 직접 호출할 수 없고, 클래스를 통해서만 호출 가능
- 주로 인스턴스의 상태와 관계없는 유틸리티 함수 구현에 사용
- this를 사용할 수 없어 인스턴스 컨텍스트에 접근 불가능
getter 와 setter
- 객체의 속성을 읽거나 설정할 때 사용되는 특별한 메서드
- getter, setter 메서드 사용 시 객체 속성에 대한 더 나은 제어가 가능하며, 코드의 안정성과 유지보수성을 높일 수 있다.
// getter (접근자)
get area() {
return this._height * this._width;
}
// setter (설정자)
set height(value) {
if (value > 0) {
this._height = value;
}
}
■ getter (접근자)
- 함수처럼 정의하지만 속성처럼 접근한다. (ex. Rectangle.area)
- 읽기 전용 속성을 만들 수 있으며 복잡한 계산된 값을 반환할 수 있다.
- private 데이터에 안전하게 접근할 수 있다.
■ setter (설정자)
- 값을 설정하기 전에 유효성 검사를 할 수 있다.
- 데이터를 가공하여 저장할 수 있다.
- 여러 속성을 한 번에 설정할 수 있다.
클래스 상속
1. 클래스 간 상속
// 모든 사람이 공통으로 가지는 기본 클래스
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
// 모든 사람이 가지는 공통 메서드
introduce() {
console.log(`안녕하세요! 제 이름은 ${this.name}이고, ${this.age}살입니다.`);
}
}
// Person을 상속받는 학생 클래스
class Student extends Person {
constructor(name, age, grade) {
// 부모 클래스의 생성자 호출
super(name, age);
this.grade = grade;
}
// 학생만의 고유한 메서드
study() {
console.log(`${this.name} 학생이 공부를 합니다.`);
}
// 부모 메서드를 확장한 메서드
introduce() {
super.introduce(); // 부모의 introduce 메서드 호출
console.log(`저는 ${this.grade}학년 학생입니다.`);
}
}
■ extends
- 다른 클래스를 상속받을 수 있는 키워드로 부모 클래스의 모든 속성과 메서드를 상속받는다.
- 여러 클래스를 동시에 상속받을 수는 없음(다중 상속 불가)
- 상속받은 메서드를 재정의(오버라이딩) 할 수 있음
■ super
- 부모 클래스의 메서드를 호출할 수 있는 키워드
① constructor(생성자) 안에서의 super
class Animal {
constructor(name) {
this.name = name;
}
}
class Cat extends Animal {
constructor(name, age) {
super(name); // 부모 클래스의 constructor 호출
this.age = age;
}
}
const myCat = new Cat("감자", 5);
- super()는 this 키워드를 사용하기 전에 호출해야 한다.
- 자식 클래스의 인스턴스가 생성되기 전에 부모 클래스의 초기화가 먼저 완료되어야 하기 때문
- constructor를 정의했다면 반드시 super()를 호출해야 한다.
- 자식 클래스가 부모 클래스의 속성과 메서드를 상속받으려면 부모 클래스가 먼저 초기화 되어야 하기 때문
② 메서드에서의 super
lass Parent {
sayHello() {
console.log("안녕하세요");
}
}
class Child extends Parent {
sayHello() {
super.sayHello(); // 부모 메서드 호출
console.log("저는 자식 클래스입니다.");
}
}
const child = new Child();
child.sayHello();
// 안녕하세요
// 저는 자식 클래스입니다.
- super.method()로 부모 클래스의 메서드를 호출할 수 있다.
- super 호출은 선택사항
- 해당 메서드가 부모 클래스의 기능을 활용할지, 아니면 완전히 새로운 동작을 할지에 따라 선택적으로 사용
2. 인스턴스 생성을 통한 상속
- 'new' 키워드를 사용해 클래스의 인스턴스를 생성하는 것도 일종의 상속으로 볼 수 있다.
- 생성된 객체(인스턴스)는 클래스의 프로토타입에 정의된 속성과 메서드를 상속받아 사용할 수 있다.
접근 제어자
- 클래스의 속성과 메서드에 대해 외부에서의 접근을 제어하기 위한 방법
- 데이터를 보호하고, 외부와 상호작용할 수 있는 인터페이스만 노출하도록 함
■ public
- 기본 접근 제어자로, 제어자 명시를 하지 않으면 기본적으로 public 이 설정된다.
- 클래스 내부와 외부에서 모두 접근 및 수정이 가능하다.
■ private
- # 기호를 사용해 선언하며, 해당 클래스 내부에서만 접근이 가능하다.
- 클래스 외부나 상속받은 클래스에서도 접근할 수 없다.
- 데이터 은닉과 캡슐화를 위해 사용된다.
■ protected (TypeScript)
- 클래스 및 상속받은 자식 클래스에서만 접근 가능하며, 외부에서는 접근할 수 없다.
- 상속 관계에서만 사용 가능한 멤버를 정의하는 데 유용하다.
■ readonly (TypeScript)
- 읽기 전용 속성을 정의하며, 선언 시 또는 생성자에서만 초기화할 수 있다.
- 이후 값이 변경되지 않아, 불변성을 보장해야 하는 데이터에 적합하다.
클래스 사용 시의 장점
- 코드 재사용성 향상
- 객체 생성을 위한 일관된 방법 제공
- 상속을 통한 코드 확장 용이
- 캡슐화를 통해 데이터를 보호
'JavaScript' 카테고리의 다른 글
arguments vs rest parameter (0) | 2024.12.23 |
---|---|
이벤트 루프와 실행 컨텍스트 (1) | 2024.12.20 |
프로토타입(prototype) (0) | 2024.12.18 |
클로저 (0) | 2024.12.15 |
콜백함수 (0) | 2024.12.14 |