15. 클래스로 틀 만들기 (클래스)/15.3 상속 (Inheritance)

15.3.1 부모의 특징을 물려받기 - 가족처럼 연결되는 특별한 방법

thejavascript4kids 2025. 7. 23. 01:27

📘 15.3.1 부모의 특징을 물려받기 - 가족처럼 연결되는 특별한 방법

여러분, 안녕하세요. 우리가 지금까지 배운 클래스들은 각각 따로따로 존재했습니다. 하지만 실제 세상에서는 많은 것들이 서로 연결되어 있어요. 예를 들어 강아지와 고양이는 모두 동물이라는 공통점을 가지고 있으면서도, 각자만의 특별한 특징도 가지고 있습니다.

이번 시간에는 이런 관계를 프로그래밍으로 표현할 수 있는 가족처럼 연결되는 특별한 방법에 대해 배워보겠습니다. 마치 부모님의 특징을 물려받으면서도 나만의 특별함을 가지는 것처럼요.

🧠 새로운 단어들과 친해지기

가족처럼 연결되는 특별한 방법을 이해하기 위해 몇 가지 중요한 단어들을 살펴보겠습니다.

단어 쉬운 설명
특징 물려받기 기존 클래스의 정보와 기능을 다른 클래스가 물려받는 것이에요
extends 특징 물려받기를 구현할 때 사용하는 특별한 단어예요
부모 클래스 특징을 물려주는 원본 클래스예요
자식 클래스 특징을 물려받는 새로운 클래스예요

extends는 "확장하다", "늘리다"라는 뜻의 영어 단어입니다. 기존 클래스의 기능을 확장해서 새로운 클래스를 만든다는 의미를 담고 있어요.

✨ 특징 물려받기의 핵심 개념

특징 물려받기는 자바스크립트에서 코드를 재사용하고 정리된 구조를 만들어주는 매우 중요한 개념입니다. 마치 가족에서 부모의 특징을 자녀가 물려받는 것처럼, 프로그래밍에서도 부모 클래스의 정보와 기능을 자식 클래스가 물려받을 수 있습니다.

가장 큰 장점은 공통된 기능을 중복해서 작성할 필요가 없다는 점입니다. 여러 클래스가 같은 기능을 필요로 할 때, 그 기능을 부모 클래스에 한 번만 작성하면 모든 자식 클래스에서 사용할 수 있어요. 또한 자식 클래스는 부모의 기능을 그대로 사용하면서도 자신만의 새로운 기능을 추가할 수 있습니다.

특징 물려받기를 사용하면 순서대로 정리된 프로그램 구조를 만들 수 있어서 코드를 이해하고 관리하기가 훨씬 쉬워집니다.

재미있는 비유: 동물 가족의 특징 물려받기

특징 물려받기를 더 쉽게 이해하기 위해 '동물 가족의 특징 물려받기'에 비유해볼게요.

모든 동물들은 공통적인 특징들을 가지고 있습니다. 이름이 있고, 나이가 있고, 먹을 수 있고, 잠잘 수 있고, 움직일 수 있어요. 이런 기본적인 특징들을 동물이라는 부모가 가지고 있다고 생각해볼 수 있습니다.

그런데 강아지는 동물의 모든 특징을 가지면서도 강아지만의 특별한 능력들이 있어요. 짖을 수 있고, 꼬리를 흔들 수 있고, 주인에게 충성할 수 있죠. 고양이도 마찬가지로 동물의 기본 특징에 더해서 야옹거리기, 그루밍하기, 높은 곳에 올라가기 같은 고양이만의 특별한 능력이 있습니다.

프로그래밍에서의 특징 물려받기도 정확히 이와 같습니다. 부모 클래스(동물)의 공통 기능은 모두 물려받으면서, 각 자식 클래스(강아지, 고양이)만의 독특한 기능을 추가할 수 있는 것이죠.

🎯 특징 물려받기를 사용하는 이유

그렇다면 우리는 왜 특징 물려받기를 사용할까요? 여러 중요한 이유들이 있습니다.

첫째로 코드 재사용성이 크게 좋아집니다. 공통된 기능을 여러 클래스에서 중복해서 작성할 필요가 없어서 시간과 노력을 절약할 수 있어요. 또한 공통 기능을 수정할 때도 부모 클래스 한 곳만 수정하면 모든 자식 클래스에 자동으로 반영됩니다.

둘째로 정리된 구조를 만들 수 있습니다. 관련된 클래스들을 가족처럼 구성해서 프로그램의 구조를 더 논리적이고 이해하기 쉽게 만들 수 있어요.

셋째로 기능 확장이 쉬워집니다. 기존 클래스의 기능을 그대로 사용하면서 새로운 기능만 추가하면 되므로, 새로운 요구사항에 쉽게 대응할 수 있습니다.

마지막으로 관리가 편해집니다. 공통 기능의 버그를 수정하거나 개선사항을 적용할 때 한 곳만 수정하면 되므로 관리가 훨씬 쉬워져요.

⚙️ 기본 사용법 살펴보기

특징 물려받기의 기본 사용법은 extends 키워드를 사용하는 것입니다.

// 부모 클래스 만들기
class 부모클래스 {
    constructor(받을정보) {
        this.정보 = 값;
    }

    부모기능() {
        // 공통 기능
    }
}

// 자식 클래스 만들기 (특징 물려받기)
class 자식클래스 extends 부모클래스 {
    constructor(받을정보) {
        super(받을정보);  // 부모 생성자 호출하기
        this.자식정보 = 값;  // 자식만의 정보
    }

    자식기능() {
        // 자식만의 기능
    }
}

특징 물려받기의 중요한 특징:

  • 자식 클래스는 부모의 모든 정보/기능 사용 가능
  • 자식 클래스에서 새로운 정보/기능 추가 가능
  • super()로 부모 생성자 호출하기 필수
  • instanceof로 부모-자식 관계 확인 가능

🧪 직접 해보면서 배우기

이제 실제 예시를 통해 특징 물려받기가 어떻게 동작하는지 자세히 알아보겠습니다.

🔹 첫 번째 예시: 동물과 강아지 클래스 만들기

첫 번째로는 가장 기본적인 특징 물려받기 관계를 만들어보겠습니다.

// 부모 클래스: 동물
class Animal {
    constructor(name, age) {
        this.name = name;        // 이름 저장하기
        this.age = age;          // 나이 저장하기
        this.energy = 100;       // 에너지를 100으로 시작하기
    }

    // 모든 동물이 할 수 있는 기본 행동들
    eat() {
        if (this.energy + 20 > 100) {
            this.energy = 100;    // 에너지가 100을 넘지 않게 하기
        } else {
            this.energy = this.energy + 20;    // 에너지를 20 늘려요
        }
        console.log(this.name + "이(가) 맛있게 먹었어요! 에너지: " + this.energy);
    }

    sleep() {
        this.energy = 100;       // 에너지를 완전히 회복해요
        console.log(this.name + "이(가) 푹 잤어요!");
    }

    getInfo() {
        console.log("이름: " + this.name + ", 나이: " + this.age + "살, 에너지: " + this.energy);
    }
}

// 자식 클래스: 강아지 (동물의 특징을 물려받아요)
class Dog extends Animal {
    constructor(name, age, breed) {
        super(name, age);  // 부모 생성자 호출하기
        this.breed = breed;  // 강아지만의 정보 추가
    }

    // 강아지만의 특별한 행동
    bark() {
        console.log(this.name + ": 멍멍! 🐕");
        if (this.energy - 5 < 0) {
            this.energy = 0;    // 에너지가 0 아래로 내려가지 않게 하기
        } else {
            this.energy = this.energy - 5;    // 짖으면 에너지가 5 줄어요
        }
    }

    wagTail() {
        console.log(this.name + "이(가) 꼬리를 흔들어요! 😊");
    }
}

// 특징을 물려받은 클래스 사용하기
let myDog = new Dog("멍멍이", 3, "골든리트리버");    // 강아지 만들기

// 부모 클래스의 기능 사용 가능
myDog.getInfo();  // 부모에서 물려받은 기능
myDog.eat();      // 부모에서 물려받은 기능

// 자식 클래스의 기능 사용
myDog.bark();     // 강아지만의 기능
myDog.wagTail();  // 강아지만의 기능

이 과정을 차근차근 살펴보면, 먼저 Animal 부모 클래스를 만들고 모든 동물의 공통 기능을 만듭니다. 그다음 Dog 클래스에서 extends Animal로 특징 물려받기를 선언하고, super()로 부모 생성자를 호출하죠. 마지막으로 강아지만의 특별한 기능들을 추가하고, 부모와 자식의 기능을 모두 사용해봅니다.

🔹 두 번째 예시: 차량과 자동차 클래스 만들기

이번에는 조금 더 복잡한 특징 물려받기 관계를 만들어보겠습니다.

// 부모 클래스: 차량
class Vehicle {
    constructor(brand, model) {
        this.brand = brand;      // 브랜드 저장하기
        this.model = model;      // 모델 저장하기
        this.speed = 0;          // 속도를 0으로 시작하기
        this.fuel = 100;         // 연료를 100으로 시작하기
    }

    // 모든 차량의 기본 기능
    start() {
        console.log(this.brand + " " + this.model + " 시동을 걸어요!");
        if (this.fuel - 1 < 0) {
            this.fuel = 0;    // 연료가 0 아래로 내려가지 않게 하기
        } else {
            this.fuel = this.fuel - 1;    // 시동 걸면 연료 1 소모
        }
    }

    accelerate(amount) {
        this.speed = this.speed + amount;           // 속도 늘리기
        if (this.fuel - 2 < 0) {
            this.fuel = 0;    // 연료가 0 아래로 내려가지 않게 하기
        } else {
            this.fuel = this.fuel - 2;    // 가속하면 연료 2 소모
        }
        console.log("가속! 현재 속도: " + this.speed + "km/h");
    }

    stop() {
        this.speed = 0;                             // 속도를 0으로 만들기
        console.log(this.brand + " 정지했어요.");
    }
}

// 자식 클래스: 자동차
class Car extends Vehicle {
    constructor(brand, model, doors) {
        super(brand, model);  // 부모 생성자 호출하기
        this.doors = doors;   // 자동차만의 정보
        this.aircon = false;  // 에어컨 상태
    }

    // 자동차만의 기능
    turnOnAircon() {
        this.aircon = true;                         // 에어컨 켜기
        if (this.fuel - 3 < 0) {
            this.fuel = 0;    // 연료가 0 아래로 내려가지 않게 하기
        } else {
            this.fuel = this.fuel - 3;    // 에어컨 켜면 연료 3 소모
        }
        console.log(this.brand + " 에어컨을 켰어요! 시원해요~");
    }

    honk() {
        console.log(this.brand + ": 빵빵! 🚗");
    }
}

// 자동차 사용해보기
let myCar = new Car("현대", "소나타", 4);    // 4문짜리 현대 소나타 만들기

// 부모 기능 사용
myCar.start();        // Vehicle에서 물려받은 기능
myCar.accelerate(50); // Vehicle에서 물려받은 기능

// 자식 기능 사용
myCar.turnOnAircon(); // Car만의 기능
myCar.honk();         // Car만의 기능

// 상태 확인
console.log("속도: " + myCar.speed + "km/h, 연료: " + myCar.fuel + "%");

이 예시를 통해 우리는 특징 물려받기가 단순히 기능뿐만 아니라 정보도 물려받는다는 것을 확인할 수 있습니다. 또한 자식 클래스에서 추가한 정보와 기능이 부모의 기능과 자연스럽게 어우러지는 것도 볼 수 있어요.

🔹 세 번째 예시: 특징 물려받기 관계 확인하기

마지막으로는 특징 물려받기 관계를 확인하는 방법을 알아보겠습니다.

// 부모 클래스: 전자제품
class Electronics {
    constructor(brand, power) {
        this.brand = brand;      // 브랜드 저장하기
        this.power = power;      // 전력 저장하기
        this.isOn = false;       // 전원 상태를 꺼진 상태로 시작하기
    }

    turnOn() {
        this.isOn = true;        // 전원 켜기
        console.log(this.brand + " 전원을 켜요!");
    }

    turnOff() {
        this.isOn = false;       // 전원 끄기
        console.log(this.brand + " 전원을 꺼요!");
    }
}

// 자식 클래스: 텔레비전
class TV extends Electronics {
    constructor(brand, power, screenSize) {
        super(brand, power);     // 부모 생성자 호출하기
        this.screenSize = screenSize;    // 화면 크기 저장하기
        this.channel = 1;        // 채널을 1번으로 시작하기
    }

    changeChannel(channel) {
        this.channel = channel;  // 채널 바꾸기
        console.log("채널을 " + channel + "번으로 바꿨어요!");
    }
}

// 인스턴스 만들고 특징 물려받기 관계 확인하기
let myTV = new TV("삼성", 100, "55인치");    // 삼성 55인치 TV 만들기

// 부모 기능 사용
myTV.turnOn();       // Electronics에서 물려받은 기능
myTV.changeChannel(5); // TV만의 기능

// instanceof로 특징 물려받기 관계 확인
console.log("myTV가 TV인가요?", myTV instanceof TV);                     // true
console.log("myTV가 Electronics인가요?", myTV instanceof Electronics);   // true
console.log("myTV가 Object인가요?", myTV instanceof Object);             // true

// 타입 확인 함수
function checkDeviceType(device) {
    if (device instanceof TV) {
        console.log("이것은 텔레비전이에요!");
        console.log("화면 크기: " + device.screenSize);
    }

    if (device instanceof Electronics) {
        console.log("전자제품의 기본 기능을 가지고 있어요!");
        console.log("전력: " + device.power + "W");
    }
}

checkDeviceType(myTV);

이 예시에서는 instanceof 확인 도구를 사용해서 인스턴스가 어떤 클래스의 인스턴스인지 확인하는 방법을 보여줍니다. 흥미롭게도 자식 클래스의 인스턴스는 부모 클래스의 인스턴스이기도 하다는 점을 확인할 수 있어요.

🔄 특징 물려받기 사용 순서 정리하기

지금까지 배운 특징 물려받기 사용 과정을 차근차근 정리해보겠습니다.

첫 번째 단계는 부모 클래스 설계하기입니다. 공통으로 사용할 정보와 기능들을 가진 기본 클래스를 만드는 것이죠. 두 번째 단계로는 extends 키워드 사용하기입니다. class 자식클래스 extends 부모클래스 형태로 특징 물려받기 관계를 선언합니다.

세 번째 단계는 super() 호출하기입니다. 자식 클래스의 생성자에서 super()를 호출해서 부모 클래스를 올바르게 준비해야 해요. 네 번째 단계로는 자식 기능 추가하기입니다. 자식 클래스만의 고유한 정보와 기능을 추가로 만듭니다.

마지막으로 다섯 번째 단계는 특징 물려받기 활용하기에서 부모와 자식의 기능을 모두 활용해서 인스턴스를 사용합니다.

🧚‍♀️ 이야기로 다시 배우기: 요리사 가문의 전통

지금까지 배운 내용을 하나의 이야기로 다시 정리해볼까요?

어느 요리사 가문에는 대대로 내려오는 요리 비법들이 있었습니다. 모든 가문의 요리사들은 기본적으로 "칼질하기", "불 조절하기", "간 맞추기" 같은 기초 요리 기술을 할 수 있었어요.

하지만 각 세대의 요리사들은 조상의 기술에 더해서 자신만의 특별한 요리법도 개발했습니다. 할아버지는 기초 요리에 더해서 "한식 요리"를 특기로 했고, 아버지는 할아버지의 모든 기술에 더해서 "중식 요리"를 익혔죠.

그리고 아들은 할아버지와 아버지의 모든 요리법을 물려받으면서도 "퓨전 요리"라는 새로운 스타일을 개발했습니다. 이렇게 각 세대는 이전 세대의 지혜와 기술을 그대로 물려받으면서도, 시대에 맞는 새로운 요리법을 추가해 나갔어요.

이처럼 프로그래밍의 특징 물려받기도 조상 클래스의 지혜(기능)를 그대로 물려받으면서 새로운 시대에 맞는 기능을 추가해 나가는 요리사 가문의 전통과 같습니다.

🧠 자주 하는 실수와 주의할 점

특징 물려받기를 사용할 때 자주 발생하는 실수들을 미리 알아두면 더 안전한 코딩을 할 수 있어요.

❌ 실수 1: super() 호출하는 것을 잊어버리기

class Animal {
    constructor(name) {
        this.name = name;    // 이름 저장하기
    }
}

// 잘못된 예시 - super() 호출하지 않음
class Dog extends Animal {
    constructor(name, breed) {
        // super(name); // 이걸 빼먹으면 에러가 나요!
        this.breed = breed;
    }
}

// 올바른 예시 - super() 호출하기
class Cat extends Animal {
    constructor(name, color) {
        super(name);  // 부모 생성자 호출하기 필수!
        this.color = color;
    }
}

// let dog = new Dog("멍멍이", "골든리트리버");  // 에러가 날 거예요!
let cat = new Cat("야옹이", "하얀색");           // 정상 작동
console.log("고양이 이름:", cat.name);

이런 실수가 발생하는 이유는 자식 클래스에서 constructor를 만들면 반드시 super()를 먼저 호출해야 부모 클래스가 올바르게 준비되기 때문입니다.

❌ 실수 2: 논리적으로 맞지 않는 특징 물려받기 관계 만들기

// 잘못된 설계 - 논리적으로 이상한 특징 물려받기
class Car {
    drive() {
        console.log("운전해요!");
    }
}

// 사람이 자동차의 특징을 물려받기? 논리적으로 이상해요
class Person extends Car {
    walk() {
        console.log("걸어가요!");
    }
}

// 올바른 설계 - 논리적으로 맞는 특징 물려받기
class Animal {
    breathe() {
        console.log("숨을 쉬어요!");
    }

    move() {
        console.log("움직여요!");
    }
}

class Human extends Animal {
    walk() {
        console.log("걸어가요!");
    }

    talk() {
        console.log("말을 해요!");
    }
}

// 올바른 사용
let person = new Human();    // 사람 만들기
person.breathe();  // 동물에서 물려받은 기능
person.walk();     // 사람만의 기능

console.log("특징 물려받기는 'A는 B이다' 관계가 성립할 때 사용해야 해요!");
console.log("사람은 동물이다 ✅, 사람은 자동차다 ❌");

특징 물려받기는 반드시 "is-a 관계" (A는 B이다)가 성립할 때만 사용해야 논리적으로 올바른 설계가 됩니다.

❌ 실수 3: 물려받지 않은 기능을 사용하려고 하기

class Vehicle {
    start() {
        console.log("시동을 걸어요!");
    }
}

class Car extends Vehicle {
    honk() {
        console.log("빵빵!");
    }
}

class Bicycle extends Vehicle {
    pedal() {
        console.log("페달을 밟아요!");
    }
}

let car = new Car();      // 자동차 만들기
let bike = new Bicycle(); // 자전거 만들기

// 올바른 사용
car.start();  // 부모에서 물려받은 기능
car.honk();   // 자신의 기능
bike.start(); // 부모에서 물려받은 기능
bike.pedal(); // 자신의 기능

// 잘못된 사용 - 다른 자식 클래스의 기능 사용 시도
try {
    car.pedal();  // Car에는 pedal 기능이 없어요!
} catch (error) {
    console.log("에러: Car 클래스에는 pedal 기능이 없어요.");
}

console.log("각 클래스는 부모와 자신의 기능만 사용할 수 있어요!");

각 자식 클래스는 부모의 기능과 자신의 기능만 사용할 수 있고, 다른 자식 클래스의 기능은 사용할 수 없다는 점을 기억해야 합니다.


연습문제 시작 전 잠깐, 생각해보니.

부모와 자식이라는 말을 쓰다 보니 문득 드는 생각이 있어요. 코드 속에서도 이렇게 세대를 이어가는 모습이 있다니요. 부모가 가진 좋은 것들은 고스란히 물려주면서, 또 새로운 세대는 거기에 자신만의 색깔을 더해가는 거죠. 마치 할머니의 레시피를 그대로 받되, 거기에 요즘 사람들 입맛에 맞는 새로운 재료를 조금씩 더하는 것처럼요. 이런 자연스러운 흐름이 코드에도 있다는 게 참 신기해요.

✏️ 연습문제로 개념 다지기

이제 배운 내용을 연습문제를 통해 확실히 익혀보겠습니다.

Ex1) 도형 부모 클래스와 사각형 자식 클래스 만들어보자

// 부모 클래스: 도형
class Shape {
    constructor(color) {
        if (color) {
            this.color = color;    // 색깔이 주어지면 저장하기
        } else {
            this.color = "검정";   // 주어지지 않으면 검정으로 하기
        }
    }

    // 모든 도형의 공통 기능
    getColor() {
        return this.color;     // 색깔 돌려주기
    }

    setColor(newColor) {
        this.color = newColor;    // 색깔 바꾸기
        console.log("색깔을 " + newColor + "로 바꿨어요!");
    }
}

// 자식 클래스: 사각형
class Rectangle extends Shape {
    constructor(width, height, color) {
        if (color) {
            super(color);  // 부모 생성자 호출하기
        } else {
            super("파랑");  // 색깔이 없으면 파랑으로 하기
        }
        this.width = width;      // 가로 저장하기
        this.height = height;    // 세로 저장하기
    }

    // 사각형의 넓이 계산하기
    getArea() {
        return this.width * this.height;    // 가로 × 세로
    }

    // 사각형의 정보 보여주기
    getInfo() {
        console.log(this.color + " 사각형: " + this.width + " x " + this.height + ", 넓이: " + this.getArea());
    }
}

// 사용해보기
let rect = new Rectangle(5, 3, "빨강");    // 빨간 사각형 만들기 (5×3)
rect.getInfo();           // 자식 기능
rect.setColor("초록");     // 부모 기능
rect.getInfo();           // 색깔이 바뀐 것 확인

이 연습을 통해 부모 클래스의 공통 기능을 자식 클래스에서 활용하는 방법을 익힐 수 있습니다.

Ex2) 학생 부모 클래스와 초등학생 자식 클래스 만들어보자

// 부모 클래스: 학생
class Student {
    constructor(name, grade) {
        this.name = name;         // 이름 저장하기
        this.grade = grade;       // 학년 저장하기
        this.subjects = [];       // 과목들을 담을 배열 만들기
    }

    // 모든 학생의 공통 기능
    addSubject(subject, score) {
        this.subjects.push({ subject: subject, score: score });    // 과목과 점수를 함께 저장하기
        console.log(this.name + ": " + subject + " " + score + "점 추가했어요!");
    }

    getAverage() {
        if (this.subjects.length === 0) return 0;  // 과목이 없으면 0 돌려주기
        let total = 0;                             // 총점을 0으로 시작하기
        for (let i = 0; i < this.subjects.length; i++) {
            total = total + this.subjects[i].score;  // 모든 점수 더하기
        }
        return total / this.subjects.length;       // 평균 계산하기
    }
}

// 자식 클래스: 초등학생
class ElementaryStudent extends Student {
    constructor(name, grade) {
        super(name, grade + "학년");  // "3학년" 형태로 저장하기
        this.playTime = 0;            // 놀이 시간을 0으로 시작하기
    }

    // 초등학생만의 기능
    play() {
        this.playTime = this.playTime + 1;    // 놀이 시간 1시간 늘리기
        console.log(this.name + "이(가) 신나게 놀았어요! 총 " + this.playTime + "시간");
    }

    getReport() {
        console.log("=== " + this.name + " (" + this.grade + ") 성적표 ===");
        console.log("과목 수: " + this.subjects.length + "개");
        console.log("평균 점수: " + this.getAverage() + "점");
        console.log("놀이 시간: " + this.playTime + "시간");
    }
}

// 사용해보기
let student = new ElementaryStudent("철수", 3);    // 3학년 철수 만들기
student.addSubject("국어", 85);  // 부모 기능
student.addSubject("수학", 90);  // 부모 기능
student.play();                  // 자식 기능
student.getReport();             // 자식 기능 (부모 기능도 활용)

이 문제는 특징 물려받기를 통해 기능을 확장하는 방법을 연습하는 데 도움이 됩니다.

🤔 조금 더 어려운 문제로 실력 확인하기

기본 연습을 마쳤다면, 이제 조금 더 깊이 있는 문제들을 통해 특징 물려받기에 대한 이해를 확인해보겠습니다.

Q1. extends를 사용한 특징 물려받기의 주요 장점 3가지를 설명해보세요.

정답:

  1. 코드 재사용성 - 공통 기능을 여러 클래스에서 중복 작성하지 않아도 되어서 개발 시간과 노력을 절약할 수 있습니다.
  2. 정리된 구조 - 가족 같은 구조로 클래스를 설계해서 프로그램을 더 논리적이고 이해하기 쉽게 만들 수 있습니다.
  3. 기능 확장 - 기존 클래스의 기능을 그대로 사용하면서 새로운 기능만 추가할 수 있어서 요구사항 변화에 쉽게 대응할 수 있습니다.

Q2. super()를 반드시 호출해야 하는 이유를 설명해보세요.

정답: super()는 부모 클래스의 생성자를 호출하는 기능입니다. 자식 클래스가 만들어질 때 부모 클래스의 초기화 작업이 먼저 완료되어야 부모의 정보와 기능을 제대로 사용할 수 있습니다. super()를 호출하지 않으면 부모 클래스가 준비되지 않은 상태에서 자식 클래스가 만들어지려고 해서 에러가 발생합니다. 마치 집의 기초 공사를 하지 않고 2층을 지으려고 하는 것과 같아요.

📚 15단원 앞부분 복습: 클래스 기본 개념들

특징 물려받기를 배우기 전에 15단원 앞부분에서 배운 클래스 기본 개념들을 복습해보겠습니다.

복습 문제 1: 클래스와 인스턴스 만들기

// 기본 클래스를 만들고 인스턴스를 생성해보세요
class Book {
    constructor(title, author) {
        this.title = title;      // 제목 저장하기
        this.author = author;    // 저자 저장하기
        this.pages = 0;          // 페이지를 0으로 시작하기
        this.isOpen = false;     // 책이 닫힌 상태로 시작하기
    }

    // 책 열기 메서드
    open() {
        this.isOpen = true;    // 책 열기
        console.log(this.title + " 책을 열었어요!");
    }

    // 페이지 추가 메서드
    addPages(pageCount) {
        this.pages = this.pages + pageCount;    // 페이지 추가
        console.log(pageCount + "페이지 추가됨. 총 " + this.pages + "페이지");
    }
}

// 인스턴스 생성하고 사용하기
let myBook = new Book("자바스크립트 배우기", "김코딩");
myBook.open();           // 자바스크립트 배우기 책을 열었어요!
myBook.addPages(100);    // 100페이지 추가됨. 총 100페이지

복습 문제 2: 정적 메서드 사용하기

// 정적 메서드를 포함한 클래스를 만들어보세요
class Calculator {
    constructor() {
        this.result = 0;    // 결과를 0으로 시작하기
    }

    // 인스턴스 메서드
    add(number) {
        this.result = this.result + number;    // 결과에 숫자 더하기
        return this;
    }

    // 정적 메서드 (클래스 이름으로 바로 사용)
    static multiply(a, b) {
        return a * b;    // 두 수 곱하기
    }

    static isEven(number) {
        return number % 2 === 0;    // 짝수인지 확인하기
    }
}

// 인스턴스 메서드 사용
let calc = new Calculator();
calc.add(5).add(3);
console.log("계산 결과:", calc.result);  // 8

// 정적 메서드 사용 (인스턴스 생성 없이)
console.log("5 × 3 =", Calculator.multiply(5, 3));    // 15
console.log("10이 짝수인가요?", Calculator.isEven(10)); // true

// 정답 설명: 정적 메서드는 클래스 이름으로 바로 호출할 수 있고,
// 인스턴스 메서드는 인스턴스를 만든 후에 사용할 수 있습니다.

지금까지 extends를 사용한 특징 물려받기의 모든 특성과 활용법을 자세히 알아보았습니다. 특징 물려받기는 코드의 재사용성을 높이고 정리된 프로그램 구조를 만들어주는 객체 지향 프로그래밍의 핵심 개념 중 하나입니다.

✅ 학습 완료 체크리스트

이번 시간에 배운 내용들을 모두 이해했는지 확인해보세요!

학습 내용 이해했나요?
상속(extends)의 개념
super() 키워드 사용법
부모와 자식 클래스의 관계
자주 하는 실수들
실전 예제 이해

📂 마무리 정보

오늘 배운 15.3.1 내용이 여러분의 자바스크립트 지식 상자에 잘 저장되었나요? 다음 시간에는 더 재미있는 내용으로 만나요!

기억할 점: 오늘 배운 내용을 꼭 연습해보시고, 궁금한 점이 있으면 언제든 다시 돌아와서 읽어보세요.


🚀 더 체계적인 JavaScript 학습을 원하신다면?
이 포스팅에서 다룬 내용을 실제로 실습해보세요!
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
📝 실시간 코드 실행 📊 학습 진도 관리 👥 체계적 커리큘럼
📚 171개 체계적 학습레슨 · 📋 855개 4지선다 연습문제 · 🆓 완전 무료 · ⚡ 즉시 시작