본문 바로가기

JavaScript/JavaScript기초

[Javascript] 클래스 상속

클래스 상속을 위한 'extends' 

클래스 선언 시 클래스명 옆에 extends '부모 클래스명' 을 이용하여 부모 클래스를 상속받을 수 있음

 

클래스를 상속받으면 부모 클래스의 메서드를 사용할 수 있음

 

class Parent {

    method(){
    
    	console.log("Im a parent class");
    }
}

class Child extends Parent {}

let MyObj = new Child();

//Child에는 method라는 메서드가 존재하지 않지만 부모로부터 상속을 받았으므로 사용 가능
MyObj.method();

 

결과

 

extends 를 통해 Child.prototype.[[Prototype]] 을 Parent.prototype 로 설정하므로 Child.prototype 에서 메서드를 찾지 못한다면 Parent.prototype 를 통해 메서드를 찾아옴

 

//Child.prototype 의 [[prototype]]는 Parent.prototype이므로 true
console.log(Child.prototype.__proto__ === Parent.prototype)

 

메서드 오버라이딩

만약 부모의 메서드를 자식 클래스에서 재정의를 할 경우가 있을수도 있는데 이렇게 자식 클래스에서 부모의 메서드를 재정의 하는것을 메서드 오버라이딩 이라고 함

 

class Parent {

    method(){
    
    	console.log("Im a parent class");
    }
}

class Child extends Parent {

	method(){
    	
        console.log("Im a child class");
    }
}

let MyObj = new Child();

MyObj.method();

 

결과

위의 결과를 보면 부모에서 정의한 메서드가 아니라 자식에서 재정의한 코드가 실행되는것을 확인

 

오버라이딩 된 메서드 말고 부모에서 정의한 메서드를 사용하고 싶은 경우가 있는데 이런 경우 super 를 이용해서 부모에서 정의한 메서드를 가져옴

 

super는 부모의 생성자를 호출하고 super로 인해 자식에서 오버라이딩 이전의 부모의 메서드를 사용할 수 있음

 

class Parent {

    method(){
    
    	console.log("Im a parent class");
    }
}

class Child extends Parent {
	
    method(){
    	super.method(); // 부모에서 정의된 method를 호출
        console.log("Im a child class");
    }
}

let MyObj = new Child();

MyObj.method();

 

결과

오버라이딩 된 메서드 내에서 부모의 메서드를 사용

하지만 화살표 함수에는 super가 없으니 super 사용 시 주의해야 함

 

생성자 오버라이딩

자식 클래스에서 생성자를 정의 할 때는 반드시 부모의 생성자를 오버라이딩 해야 함 생상자 오버라이딩은 constructor 내부에 super(...) 를 통해 부모 생성자에 인수를 전달해야 함

 

주의할 점은 this를 사용하기 전에 반드시 super로 부모에 인수를 전달해야 한다는 점임

 

자식 클래스의 생성자에서 super(...) 를 사용하지 않았을 경우

class Parent {
	
    constructor(value){
    	this.value = value;
    }
    method(){
    
    	console.log("Im a parent class");
    }
}

class Child extends Parent {
	
    constructor(value){
    	this.value = value;
    }
    method(){
    	super.method(); // 부모에서 정의된 method를 호출
        console.log("Im a child class");
    }
}

let MyObj = new Child('hi');

 

결과

반드시 super를 호출해야 한다는 오류가 발생

 

super로 부모에 인수를 전달

class Parent {
	
    constructor(value){
    	this.value = value;
    }
    method(){
    
    	console.log("Im a parent class");
    }
}

class Child extends Parent {
	
    constructor(value){
    	//super를 이용해 부모에 인수를 전달
    	super(value);
    	this.value = value;
    }
    method(){
    	super.method(); // 부모에서 정의된 method를 호출
        console.log("Im a child class");
    }
}

let MyObj = new Child('hi');

 

클래스 필드 오버라이딩

클래스 필드 오버라이딩시 초기화 순서를 주의할 필요가 있음

 

아무것도 상속받지 않은 기본 클래스에서는 생성자 실행 이전에 필드가 초기화 되지만 부모가 있는 클래스의 경우 생성자가 실행된 후 클래스 필드가 초기화 됨

 

class Parent {
	
    value = 'Its parent';
    constructor(){
   		
        //생성자 실행 시 method() 를 호출
        console.log(this.method());
    }
    method(){
    	
        //클래스 필드에 정의된 value를 사용
    	console.log(this.value);
    }
}

class Child extends Parent {
	
    //부모의 value를 오버라이딩
    value = 'Its child';
    constructor(){
    	super();
    }
}

let MyObj = new Child();

 

결과

 

위 결과를 보면 자식 클래스를 생성했는데 부모의 value가 호출된 것을 볼 수 있음

 

이유는 Child 가 new 로 생성될 때 먼저 생성자가 호출 -> super를 통해 부모 생성자가 호출이 되는데, 이때 Parent는 기본 클래스 이고 Child는 자식 클래스 이므로 value는 생성자 호출전에 초기화 된 부모의 value 인 것임

 

자식의 value는 생성자가 실행된 이후에 초기화가 되므로 생성자에서 실행된 value의 값은 부모의 value.

 

클래스 필드를 오버라이딩 할때는 이러한 조건을 파악한 후 주의해야 함

 

참조: https://ko.javascript.info/class-inheritance