TIL 27 | JavaScript 객체 지향 프로그래밍 04

Saemsol Yoo·2020년 12월 30일
0

javascript

목록 보기
18/25
post-thumbnail

생활코딩 객체 지향 프로그래밍 수업을 보며 정리한 내용입니다.


Inheritance 상속

1. 상속이 필요한 이유

지난번에 만들어 보았던 class 이다.

class Person {
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  }
  sum() {
    return this.first + this.second;
  }
}

이 클래스에는 sum 이라는 method 만 있는데, 만약 평균을 구해주는 method 도 필요해졌다면 어떻게 해야할까?

① class 수정

  • 필요한 코드를 추가해서 class를 수정
class Person {
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  }
  sum() {
    return this.first + this.second;
  }
  
  //원하는 새로운 코드 추가해서 수정하기!
  avg() {
    return (this.first + this.second) / 2;
  }
}

물론 이렇게 직접 Person이라는 class에 직접 작성해 수정해줘도 되겠지만
언제나 이렇게 수정해줄 수 는 없다. 수정할 수 없는 경우는,

  1. 이 class 를 직접 만든게 아니라 다른사람이 만들었다거나,
  2. 혹은 외부 라이브러리에서 가져다 사용하는 경우

라면 여러 문제가 발생할 수도 있기 때문이다.
→ 이 코드를 수정해 버리면 그 class가 업데이트 되었을 때 내가 작업한 것을 덮어써 버리거나, 수정한 부분으로 인해 업데이트를 못하게 되는 곳이 생기는 등의 문제가 발생.

혹은 내가 직접 작성한 코드일지라도 class 안에서 기존 Person의 기능은 최소한으로 유지하면서 추가적으로 평균이 필요한 경우가 전체코드 중에 되게 일부분일 수도 있는데,
→ 일부분에서만 필요한 것 때문에 모든 곳에서 사용하는 코드를 추가하는 것은 되게 부담스러운 일이 될 수 있기 때문이다.

② 새로운 class 만들기

아니면 기존 class의 코드를 수정하지 않고 새로운 class를 하나 더 만드는 방법도 있다.

class Person { 					  //기존 코드는 그대로 두고,
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  }
  sum() {
    return this.first + this.second;
  }
}

class PersonPlus {                                //새로운 class를 만들어준다.
  //위에 있는 코드를 그대로 카피해 붙여넣기 한 다음에
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  }
  sum() {
    return this.first + this.second;
  }

  //그 다음에 여기에 원하는 새로운 코드 추가
  avg() {
    return (this.first + this.second) / 2;
  }
}

그런데 이렇게 했을 경우에는 큰 아쉬움이 생기는데, 그건 바로 중복이다.
기존 Person에 있는 코드가 PersonPlus에도 또 있게된다.

👏🏻 그래서 이런 중복을 없애면서, 이렇게 추가해주는것을 가능하게 해주는 것이 바로 상속이다!

③ Inheritance 상속 ✨

extends 라는 키워드를 이용해서 기존 class를 상속해 새로운 class를 만들어주면 된다!

class PersonPlus extends Person { //Person이라고 하는 class를 확장(extends)한다. 라고 적어주기!
  /* 이제는 이렇게 중복되는 코드는 지워버리기~
  ... 그럼 extends Person에 의해서 class가 가지고 있는 요소들이 그대로 상속되는것이다. (=로딩되는거다 PersonPlus에!)
  
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  } 
  sum() {
    return this.first + this.second;
  }
  */

  avg() {
    return (this.first + this.second) / 2;
  }
}

→ 이렇게 상속을 이용했을 때의 효과는 😇

  1. 중복되는 코드를 상속기능으로 제공했기 때문에, 코드의 양이 줄었고
  2. 중복해서 사용하고있는 부분을 바꾸면 해당 class를 상속하고있는 모든 class에서 동시다발적으로 변경이 일어날 수 있다. (유지보수의 편의성 도모)

이로써 상속을 통해 무엇을 할 수 있는지, 상속이 없으면 무엇이 불편한지, 상속을 할 때 extends라는 키워드를 쓰게 되는데, 상속받는 자식클래스는 어떻게 구현하면 되는 지를 알 수 있게 되었다.




2. 상속의 단점 보완

class Person {
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  }
  sum() {
    return this.first + this.second;
  }
}

class PersonPlus extends Person {
  avg() {
    return (this.first + this.second) / 2;
  }
}

→ 이렇게 상속을 이용해(extends) 만든 class에서는 first와 second만 있는데, 이뿐만 아니라 third 까지 있길바란다면 어떻게 해야할까?

① 또 다시 덧붙여 쓰기

🚨 하지만 아래 코드는 동작하지 않는 코드이다. (이유는 현재로선 중요하지 않다.)

class Person {
  constructor(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
  }
  sum() {
    return this.first + this.second;
  }
}

class PersonPlus extends Person {
  constructor(name, first, second, third) {
    this.name = name;
    this.first = first;
    this.second = second;
    this.third = third;
  }
  sum() {
    return this.first + this.second + this.third;
  }
  avg() {
    return (this.first + this.second + this.third) / 3;
  }
}

→ 하지만 이렇게 되면, 상속 이란걸 쓰는 의의가 전혀 없어지고 원점으로 돌아와 버린다. (왜냐면 코드가 또 반복되니까!)

그래서 이럴 때 사용하는 키워드가 바로 super 이다.

② super 사용하기

super 은 부모클래스를 불러서 부모클래스에게 일을 시키고, 부모가 하지 못하는 일은 자식클래스가 하도록 하는 기능이다. 그래서 super 를 이용하면 부모가 가지고 있는 기능을 실행시킬 수 있다.

super을 사용할 때에는 두가지 용법이 있는데,

  • super( ) : 뒤에 괄호가 붙는 경우 → 부모class의 생성자가 호출
  • super. : 뒤에 점이 붙는 경우 → 부모 클래스라고 생각하자!
class PersonPlus extends Person {
  constructor(name, first, second, third) {
    super(name, first, second); //super 괄호 열고, 괄호 닫고
    // .. 이렇게 해주면  PersonPlus의   부모class(=Person) 의 생성자가 호출이 되고
    // 그 생성자 안에서 property 들이 세팅이 되기 때문에,
 
    this.third = third; //자식은 이것만 해주면 되는거다.
  }

  // 자. 그다음에  sum이라고 하는 것도 만약 1억줄 짜리 코드라면, 
  // .. 그래서 자식이 코드를 다시 구현하는 것이 대단히 비효율적인 상황이 될 수 있다라면?
  // --> 우리는 부모클래스에 있는 sum을 호출하고 그 결과를 받고, 
  //     자식클래스에서 다시 추가적인 작업을 해주면 좋지 않을까?
  sum() {
    return super.sum() + this.third; 
    //이렇게 하면 부모가 갖고있는 sum이 호출이 되고, 
    //그 결과가 return되고 그 결과에다 추가적인 작업(+this.third)를 해서 리턴해주면 되는거다.
  }
}

→ 이렇게 부모가 가지고 있는 기능과, 자식이 가지고 있는 기능의 중복을 제거하기 위해 super 를 사용!

그럼 여기까지, 다음 질문들에 대답을 생각해보자.

  • super라고 하는 것은 어떤 용법(2가지)들이 있는지?
  • 괄호가 있을 때 그건 무엇이고,
  • 괄호가 없을 땐 그건 무엇인지.
  • super가 없다면 우린 어떤 불편함이 있고
  • super가 있다면 우린 어떤 편리함을 얻게 되는지!
  • 상속이란 기능으로 인해 생기는 단점과, 그것을 어떻게 보완할 수 있을까?
profile
Becoming a front-end developer 🌱

0개의 댓글