JavaScript 클래스 상속

seul_velog·2021년 12월 12일
0

JavaScript

목록 보기
17/25
post-thumbnail

📍 1. 클래스 상속(Class Inheritance)

클래스 상속을 사용하면 클래스를 다른 클래스로 확장할 수 있다.
extends 키워드를 사용하여 클래스 상속을 생성한다.



📌 다형성

들어가기 전에 '다형성' 에 대해서 먼저 알아보자!

다형성(polymorphism) 이라는 단어는 원래 '여러 개의 형태를 갖는다' 라는 의미의 그리스어에서 유래했다. 또 사전에서 찾아보면 poly(하나 이상), morph(형태)가 합성된 단어로 '하나 이상의 형태'를 뜻한다.

다형성의 개념에 대해 먼저 알아본다면 객체지향에서 다형성의 개념이 적용된 두 가지 형태인 오버로딩오버라이딩 을 이해하기 좋을 것이다.

  • 오버로딩(overloading) : 메서드 중복 정의
  • 오버라이딩(overriding) : 메서드 재정의

다형성 ex.1 )

  • 위 그림에서 공통점은 (수단은 다르지만) 무언가를 '타다'라는 동사가 동일하다는 것이다.

다형성 ex.2 )

  • '삼각형의 면적 계산' , '사각형의 면적 계산' , '원의 면적 계산' 이 세가지의 공통점은 면적을 계산한다는 것이다.
  • 도형에 따라 달라지는 면적 공식이다. 즉, 모든 도형에 대해 면적을 구하는 메서드 이름은 모두 동일하지만 이 메서드를 구현하는 부분에서는 다음과 같이 각기 다른 공식을 사용하게 된다. 만약 사다리꼴 면적도 구해야한다면 사다리꼴 객체를 추가하면 된다. (유지보수의 용이)

위의 예에서 살펴보면 하나의 행위('타다', '면적을 계산하다')가 결과를 여러개 만들어 내는 것을 알 수 있다. 이는 프로그램 측면에서 같은 메세지에 대해 이 메세지를 수신하는 객체마다 다르게 행동하는 것을 의미한다. 동일한 메서드 이름을 사용하지만 메서드에 대해 클래스마다 모두 다르게 구현되는 개념이 다형성이다.



1-1. 클래스 생성

✏️ 예제를 작성하면서 과정을 다시 복습 & 정리해보기.

class Shape {
  constructor(width, height, color){
    this.width = width;
    this.height = height;
    this.color = color;
  }

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

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

let shape = new Shape(3, 3, 'blcak');
console.log(shape.width);  // 3
console.log(shape.draw());  // drawing blcak color !

✍️
(1) Shape 이라는 클래스를 만들었다. Shape 안에는 세 가지의 fields (width, height, color)가 있고, 두 가지의 methods (draw(), getArea())가 있다.
(2) new Shape(...)를 호출해서 shape 라는 객체를 만들었다. 넘겨받은 인수와 함께 constructor 가 실행되고 할당이 잘 되었는지 확인!



1-2. extends 키워드를 통해 상속받기(1)

❓ 만약 Rectangle 이라는 클래스를 만든다고 가정해보자. 그리고 그 안의 데이터가 Shape 클래스와 동일한 데이터가 필요하다면 ▶ extends(연장하다) 를 통해 상속할 수 있다.

✏️ Shape 를 상속받는 class Rectangle 을 만들어보자.

class Shape {
  constructor(width, height, color) {
    this.width = width;
    this.height = height;
    this.color = color;
  }

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

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


// ▼ 
class Rectangle extends Shape {}

const rectangle = new Rectangle(10, 20, "blue");
console.log(rectangle.width);  // 10
console.log(rectangle.draw());  // drawing blue color !
console.log(rectangle.getArea());  // 200

✍️
(1) 클래스 확장 문법 class Child extends Parent 을 사용해서 Rectangle 클래스를 확장해보자.
(2) Shape 에서 정의한 fieldsmethods 가 자동적으로 Rectangle 에 포함된다.
(3) 콘솔을 통해 결과를 확인해보자!



1-3. extends 키워드를 통해 상속받기(2)

✏️ Shape 를 상속받는 class Triangle 을 만들고 Shape 내에서 수정해보자.

class Shape {
  constructor(width, height, color) {
    this.width = width;
    this.height = height;
    this.color = color;
  }

  draw() {
    return (`drawing ${this.color} color :) !! `); // ◀ 여기서 수정하면
  }

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


// ▼ Rectangle 
class Rectangle extends Shape {}

const rectangle = new Rectangle(10, 20, "blue");
console.log(rectangle.width);  // 10
console.log(rectangle.draw());  // drawing blue color :) !! // ◀ 수정됨
console.log(rectangle.getArea());  // 200


// ▼ Triangle
class Triangle extends Shape {}

const triangle = new Triangle(5, 30, 'white');
console.log(triangle.height);  // 30
console.log(triangle.draw());  // drawing white color :) !! // ◀ 수정됨
console.log(triangle.getArea()); // 150

✍️
(1) 이렇게 상속을 사용하게 되면 공통되어지는 데이터를 일일이 작성하지 않고도 extends 를 사용해서 계속 재사용할 수 있다.
(2) 만약 공통적으로 수정이 필요할 때에도 class Shape 안에서 수정을 하면 동시에 적용된다.



1-4. 오버라이딩

❓ 앞에서 class Rectangleclass Triangle 을 만들었는데 이것들은 각각 Shapefileds 를 사용해서 getArea을 구했다. 그런데 삼각형의 넓이를 구하는 공식은 밑변 * 높이의 곱의 1/2로 구해야 한다.

✏️ 여기서 필요한 함수만 재정의해서 쓸 수 있다.(오버라이딩)
우리가 앞에서 살펴본 '다형성' 이 빛을 발하는 순간이다!

class Shape {
  constructor(width, height, color) {
    this.width = width;
    this.height = height;
    this.color = color;
  }

  draw() {
    return `drawing ${this.color} color :) !! `;
  }

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


// ▼ Rectangle 
class Rectangle extends Shape {}

const rectangle = new Rectangle(10, 20, "blue");
console.log(rectangle.width); // 10
console.log(rectangle.draw()); // drawing blue color :) !!
console.log(rectangle.getArea()); // 200


// ▼ Triangle
class Triangle extends Shape {
  getArea() {
    return (this.width * this.height) / 2;  // 자체정의 메소드
  }

  draw() {
    return (`${super.draw()} 🔼 `); // super 키워드 사용
  }
}

const triangle = new Triangle(5, 30, "white");
console.log(triangle.height); // 30
console.log(triangle.draw()); // drawing white color :) !!  🔼  
console.log(triangle.getArea()); // 75

✍️
(1) 이렇게 메소드를 오버라이딩 할 수 있다.

  • 부모 메서드를 토대로 일부 기능만 변경하고 싶을 경우나 부모 메소드의 기능을 확장하고 싶을 때 이렇게 커스텀 메소드를 작업하게 된다.
  • 그런데 Triangle 에서 메소드를 자체적으로 정의하면, 상속받은 메소드가 아닌 자체 메소드가 사용된다. ( 더이상 Shape 에 정의된 함수가 호출되지 않게 된다. )
  • 이 때 키워드 super 를 사용한다.

(2) 부모 메소드의 draw() 도 출력하고, Triangle 에서 오버라이딩으로 재정의한 draw() 도 함께 출력하고 싶을 때 키워드 super 를 사용한다.
super.draw() : 부모의 draw 라는 의미이다. 이 함수를 호출하면 부모의 메소드도 호출된다.

  • super.method(...) 는 부모 클래스에 정의된 메소드, method 를 호출한다.
  • super(...) 는 부모 생성자를 호출하는데, 자식 생성자 내부에서만 사용 할 수 있다.

✍️ 작성 중간에 undefined 가 몇번 떴는데, 콘솔과 리턴이 엇갈리게 작성되어 있었다. 😓 하지만 콘솔과 리턴 부분을 계속해서 조정 해줌으로써 원하는 결과를 출력하고, 이 둘의 동작원리를 더 이해할 수 있게 되었다.


2. instanceof

instanceof 연산자는 생성자의 prototype 속성이 객체의 프로토타입 체인 어딘가 존재하는지 판별한다.

object instanceof constructor

  • object : 판별할 객체
  • constructor : 판별 목표 함수
  • 즉, 왼쪽에 있는 오브젝트가 오른쪽에 있는 클래스의 인스턴스 인지 아닌지를 확인하여 true 나 false 를 리턴한다.

📌 위의 클래스상속 예제를 통해 instanceof 를 사용하면 아래와 같은 결과가 나온다.

console.log(rectangle instanceof Rectangle);  // true
console.log(triangle instanceof Rectangle);  // false
console.log(triangle instanceof Triangle);  // true
console.log(triangle instanceof Shape);  // true (Shape을 상속했으므로)
console.log(triangle instanceof Object);  // true

✍️
마지막행의 triangle instanceof Object → true
: 자바스크립트에서 만든 모든 오브젝트 클래스들은 자바스크립트에 있는 오브젝트를 상속한 것이기 때문이다. 그 말은 우리가 어떤 오브젝트든지 이 공통적으로 존재하는 메소드를 쓸 수 있다는 것이다.( toString(), constructor() 등 )

  • Object.prototype.toString()은 문자열을 반환하는 object의 대표적인 방법이다.
// 위의 예제를 빌려와서 작성
class Triangle extends Shape {
  getArea() {
    return (this.width * this.height) / 2;
  }

  draw() {
    return (`${super.draw()} 🔼 `);
  }
  
  toString(){
        return (`Triangle 이고, 색은 ${this.color} 입니다.`) 
  }
}

const triangle = new Triangle(5, 30, "white");

console.log(triangle.toString()); // Triangle 이고, 색은 white 입니다.

📌 자바스크립트 내장객체 - JavaScript의 내부에 포함되어 있는 오브젝트는 어떤 것들이 있는지 카테고리로 묶여서 정리되어 있다.




reference
javascript.info MDN-instanceof dreamcoding 네이버지식백과-다형성

profile
기억보단 기록을 ✨

0개의 댓글