본문 바로가기
JavaScript

[JavaScript] 클래스, 상속, 다형성

by happenstance 2021. 8. 6.
'use strict';
// Object-oriented programming
// class: template
// object: instance of a class
// JavaScript classes
// - introduces in ES6
// - syntactical sugar over prototype-based inheritance

// 1. Class declarations
class Person {
    // constructor
    constructor(name, age) {
        // fields
        this.name = name;
        this.age = age;
    }

    // methods
    speak() {
        console.log(`${this.name}: hello!`);
    }
}

// object 생성
const jh = new Person('jh', 20);
console.log(jh.name);
console.log(jh.age);
jh.speak();

// 2. Getter and setters
class User {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    // get age()를 정의하는 순간 this.age는 메모리에 올라가있는 데이터를 읽어오는 것이 아니라
    // 바로 getter를 호출함
    get age() {
        return this._age;
    }

    // set age()를 정의하는 순간 값을 할당할 때 메모리에 값을 할당하는 것이 아니라
    // 바로 setter를 호출함
    set age(value) {
        this._age = value < 0 ? 0 : value;
    }
}
// 결국 User라는 클래스 안에는 3개의 field가 존재함
// firstName, lastName, _age

// 클래스를 사용하는 사용자가 잘못된 인수를 입력하지 않도록 막아주는 역할을 함
const user1 = new User('Steve', 'Job', -1); // age가 -1 이라는 것은 잘못된 것
console.log(user1.age);

// 3. Fields (public, private)
// 최근에 추가됨
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference 자바스크립트 object들
class Experiment {
    publicField = 2; // 외부에서 접근 가능
    #privateField = 0; // 외부에서 접근 및 변경 불가능(내부에서만 접근 및 변경 가능)
}
const experiment = new Experiment();
console.log(experiment.publicField);
console.log(experiment.privateField); // undefined

// 4. Inheritance
// a way for one class to extend another class.
class Shape {
    constructor(width, height, color) {
        this.width = width;
        this.height = height;
        this.color = color;
    }

    draw() {
        console.log(`drawing ${this.color} color!`);
    }

    getArea() {
        return this.width * this.height;
    }
}

class Rectangle extends Shape {}
class Triangle extends Shape {
    // 내가 필요한 함수만 재정의하여 사용할 수 있음 => 다형성
    // Shape() class의 getArea()를 재정의 함
    getArea() {
        return (this.width * this.height) / 2;
    }
    draw() {
        // super.draw(); => 부모의 draw()도 함께 호출됨
        console.log('🔺');
    }
}

// 출력 내용이 잘못 되었다면 draw() 메소드만 수정하면 됨
const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw(); // drawing blue color!
const triangle = new Triangle(20, 20, 'blue');
triangle.draw(); // 🔺

// getArea()는 rectangle, triangle 각각 구하는 방식이 다름
// 이때 다형성이 필요함
console.log(rectangle.getArea()); // 400
console.log(triangle.getArea()); // 200

// 5. Class checking: instanceOf
console.log(rectangle instanceof Rectangle); // rectangle이 Rectangle의 instance인지 확인하는 것
console.log(triangle instanceof Rectangle); // false
console.log(triangle instanceof Triangle); // true
console.log(triangle instanceof Shape); // true
console.log(triangle instanceof Object); // true