4.1 상속 — 이건 정말 쉬워
상속은 객체 지향 프로그래밍 (OOP)의 기본 개념 중 하나야. 이걸로 하나의 클래스(자식 클래스 또는 서브클래스라고 해) 다른 클래스(부모 클래스 또는 슈퍼클래스라고 불러)의 필드와 메소드를 상속받을 수 있어.
이 방법으로 일반적인 클래스를 만들고 코드를 재사용할 수 있어. 그래서 코드 조직과 유지 보수가 더 좋아져.
왜 상속이 필요할까?
예를 들어 어떤 코드를 작성해야 한다고 가정해봐. 그리고 이걸 클래스 형태로 작성하기로 했다고 치자. 그런데 프로젝트에 이미 당신이 원하는 거의 모든 작업을 하는 클래스가 있다고 하자. 그럼 그냥 그 클래스의 코드를 복사해서 사용해도 돼.
아니면 "복사한 것처럼" 할 수도 있지. 그 클래스를 자신의 클래스의 부모로 선언하면 JavaScript가 당신의 클래스에 부모 클래스의 행동을 추가할거야.
마치 자연이 되고 싶고 개를 만들고 싶다고 상상해봐. 박테리아로 개를 만드는 데 10억년 걸릴까, 아니면 20만년 만에 늑대를 길들이는 게 더 빠를까?
4.2 프로토타입을 통한 상속의 개념
JavaScript에서의 프로토타입 상속은 객체들이 다른 객체의 속성과 메소드를 상속받을 수 있게 하는 주요 메커니즘 중 하나야. 이렇게 하면 복잡한 객체 계층 구조를 만들고 코드를 재사용할 수 있어.
JavaScript의 모든 객체는 자신의 프로토타입을 가리키는 숨겨진 속성 [[Prototype]]을 가지고 있어. 프로토타입은 상속을 구현하기 위해 사용되고, 이를 통해 객체들이 다른 객체로부터 속성과 메소드를 상속받을 수 있어.
간단한 상속 예제
단계 1: 기본 객체 생성하기
const animal = {
eat() {
console.log('Eating...');
},
sleep() {
console.log('Sleeping...');
}
};
단계 2: 상속 객체 생성하기
const dog = Object.create(animal);
dog.bark = function() {
console.log('Barking...');
};
단계 3: 상속된 속성과 메소드 사용하기
dog.eat(); // 결과: Eating...
dog.sleep(); // 결과: Sleeping...
dog.bark(); // 결과: Barking...
이 예제에서 dog 객체는 animal 객체로부터 eat()과 sleep() 메소드를 상속받고 자신만의 bark() 메소드를 추가해.
4.3 깊은 프로토타입을 통한 상속
프로토타입 체인
JavaScript에서 객체들이 서로 상속되어 프로토타입 체인을 형성할 때 상속은 더 복잡해질 수 있어.
프로토타입 체인 예제
이 예제에서 dog 객체는 mammal 객체로부터 상속받고, mammal은 animal로부터 상속받아. 이렇게 하면 dog는 mammal과 animal의 모든 메소드에 접근할 수 있는 프로토타입 체인을 생성해.
const animal = {
eat() {
console.log('Eating...');
}
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Walking...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Barking...');
};
dog.eat(); // 결과: Eating...
dog.walk(); // 결과: Walking...
dog.bark(); // 결과: Barking...
프로토타입 체인 확인
isPrototypeOf() 메소드를 사용하면 객체가 다른 객체의 프로토타입인지를 확인할 수 있어.
예제:
console.log(animal.isPrototypeOf(mammal)); // 결과: true
console.log(mammal.isPrototypeOf(dog)); // 결과: true
console.log(animal.isPrototypeOf(dog)); // 결과: true
4.4 메소드 오버라이딩
프로토타입 상속은 새로운 메소드를 추가하는 것뿐만 아니라 기존 메소드를 오버라이딩하는 것도 가능해.
메소드 오버라이딩 예제
이 예제에서 dog 객체의 speak() 메소드는 animal 객체의 speak() 메소드를 오버라이딩해.
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak = function() {
console.log('Dog barks');
};
animal.speak(); // 결과: Animal speaks
dog.speak(); // 결과: Dog barks
부모 객체 메소드 호출
JavaScript에서 부모 객체의 메소드를 호출하려면 call() 또는 apply() 메소드를 사용할 수 있어.
예제:
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak = function() {
animal.speak.call(this);
console.log('Dog barks');
};
dog.speak();
// 결과:
// Animal speaks
// Dog barks
4.5 프로토타입 상속의 심화된 사용법
내장 객체 확장
JavaScript의 내장 객체를 확장하여 그들의 프로토타입에 메소드를 추가할 수 있어.
예제:
Array.prototype.sum = function() {
return this.reduce((acc, value) => acc + value, 0);
};
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.sum()); // 결과: 15
다단계 계층 구조 생성
프로토타입 상속을 사용하여 보다 복잡한 다단계 객체 계층 구조를 생성할 수 있어.
예제:
const livingBeing = {
breathe() {
console.log('Breathing...');
}
};
const animal = Object.create(livingBeing);
animal.eat = function() {
console.log('Eating...');
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Walking...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Barking...');
};
dog.breathe(); // 결과: Breathing...
dog.eat(); // 결과: Eating...
dog.walk(); // 결과: Walking...
dog.bark(); // 결과: Barking...
GO TO FULL VERSION