본문 바로가기

자바스크립트

[Javascript] - 클래스 상속

 

 

extends 키워드

 

 

- Animal이라는 클래스를 만들었다.

 

 

- 위 그림은 객체 animal과 클래스 Animal의 관계를 그림으로 표현한 것이다

 

 

- 위 예제에서 또 다른 클래스 Rabbit을 만들었다 Rabbit은 Animal을 상속받는다.

 

- 클래스 확장 문법 class Child extends Parent를 사용해 클래스를 확장할 수 있다 또는 상속받을 수 있다.

 

- 키워드 extends는 프로토타입을 기반으로 동작한다 extends는 Rabbit.prototype.[[Prototype]]을 

Animal.prototype으로 설정한다 그렇기 때문에 Rabbit_prototype에 메서드를 찾지 못하면 Animal.prototype에서 메서들르 가져온다.

 

- 따라서 클래스 Rabbit을 사용해 만든 rabbit은 hide 같은 Rabbit 에 정의된 메서드에도 접근할 수 있고 run과 같은 Animal에 정의된 메서드에도 접근할 수 있다.

 

 

 

- 엔진은 다음 절차를 따라 메서드 rabbit.run의 존재를 확인한다.

 

1 객체 rabbit에 run이 있나 확인한다 확인 결과 run이 없다.

 

2 rabbit의 프로토타입인 Rabbit.prototype에 메서드가 있나 확인한다 hide는 있는데 여전히 겨ㅜㅇ 은 없다.

 

3 extends를 통해 관계가 만들어진 Rabbit.prototype의 프로토타입인 Animal.prototype에 메서드가 있나 확인한다 드디어 run을 찾았다.

 

- 네이비트 프로토타입에서 알아본 것처럼 자바스크립트의 내장 객체는 프로토타입을 기반으로 상속 관계를 맺는다

 

- Date.prototype.[[Prototype]]이 object.prototype인 것처럼 Date 객체에서 일반 객체 메서드를 사용할 수 있는 이유가 바로 여기에 있다.

 

extends 뒤에 표현식

 

 

 

- 위 예제처럼 클래스 문법은 extends 뒤에 표현식이 와도 처리해준다 class User는 

f('Hello') 반환 값을 상속받는다.

 

- 위 방법은 조건에 따라 다른 클래스를 상속받고 싶을때 유용하다 조건에 따라 다른 클래스를 반환하는 함수를 만들고 함수 호출 결과를 상속받게 하면 된다.

 

메서드 오버라이딩

 

- 객체 지향에서 오버라이딩이란 부모 클래스에서 상속받은 내용을 자식 클래스에서 변형하는 것을 의미한다

- 위에서 예제에서 특별한 사항이 없으면 class Rabbit 은 class Animal에 있는 메서드를 그대로 상속받는다 그런데 Rabbit에서 stop등의 메서드를 자체적으로 정의하면 상속받은 메서드가 아닌 자체 메서드가 사용된다

 

 

- 개발을 하다보면 부모 메서드 전체를 고려하지 않고 부모 메서드를 토대로 일부 기능만 변경하고 싶을 때가 생기ㅏㄴ다 부모 메서드의 기능을 확장하고 싶을 때도 있다.

 

- 이럴 때 메서드 오버라이딩을 통해 커스텀 메서드를 만들어 작업하게 된다.

 

 

- 위 예제처럼 만약 이미 커스텀 메서드를 만들었더라도 이 과정 전 후에 부모메서드를 호출하고 싶을 때도 있는데 

이럴때는 키워드 super를 사용한다.

 

생성자 오버라이딩

 

- 생성자 오버라이딩은 조금 까다롭다 지금까지 Rabbit 에 자체 constructor가 없었다.

 

 

- 명세서에 따르면 클래스가 다른 클래스를 상속 받고 constructor가 없는 경우에는 위 예제처럼 비어ㅗ있는 constructor가 생성된다.

 

- 보시다싶이 생성자는 기본적으로 부모 constructor를 호출한다 이때 부모 constructor에도 인수를 모두 전달한다 클래스에 자체 생성자가 없는 경우에는 이런 일이 모두 자동으로 일어난다.

 

 

 

- Rabbit에 커스텀 생성자를 추가했다 커스텀 생성자에 name과 earLength를 지정하였다.

- 위와 같이 실행하면 에러가 발생한다 이유는 다음과 같다.

 

상속클래스의 생성자엔 반드시 super(...)를 호출해야 하는데 super(...)를 호출하지 않아 에러가 발생했다 super(...)는 this를 사용하기 전에 반드시 호출해야 한다.

 

그런데 왜 super(...)를 호출해야 할까 그이유는 상속 클래스의 생성자가 호출될 때 다음과 같은 일이 발생하기 때문이다.

 

1. 자바스크립트는 상속 클래스 생성자 함수와 그렇지 않은 생성자 함수를 구분한다. 상속 클래스의 생성자 함수에는 특수 내부 프로퍼티인 [[ConstructorKind]: 'derived"가 이름표처럼 붙는다.

 

2 일반 클래스의 생성자 함수와 상속클래스의 생성자 함수 간 차이는 new와 함께 드러난다.

 

3 일반 클래스가 new와 함께 실행되면 빈 객체가 만들어지고 this에 이 객체를 할당한다.

 

4 반면 상속 클래스의 생성자 함수가 실행되면 일반 클래스에서 일어난 일이 일어나지 않는다 상속 클래스의 생성자 함수는 빈 객체를 만들고 this에 이 객체를 할당하는 일을 부모 클래스의 생성자가 처리해주길 기대하기 때문이다

 

- 결론은 위와 같은 차이 때문에 상속 클래스의 생성자에선 super를 호출해 부모 생성자를 실행해주어야 한다 그렇지 않으면 this가 될 객체가 만들어지지 않아 에러가 발생한다.

 

 

 

- 위 예제처럼 this를 사용하기 전에 super()를 호출하면 Rabbit의 생성자가 제대로 작동한다