개발계발/Javascript

Javascript 객체 지향[2] - class 상속/super/object 상속/__proto__ vs prototype

냥냥친구 2019. 7. 2. 22:18

2019/06/29 - [공부/JS] - Javascript 객체 지향[1] - this/constructor/prototype

 

Javascript 객체 지향[1] - this/constructor/prototype

자바스크립트는 객체지향 스크립트 언어이다. 객체지향을 내 기준에서 간단하게 설명하면 자주 사용하는 걸 구조화해놓는 것이다. 그러면 필요할 때마다 만들지 않아도 되고 이미 만들어진 걸 가져다 쓰기만 하면..

myphiloprogramming.tistory.com

 

1. class 상속

클래스를 생성할 때 다른 클래스를 상속 받을 수 있는데, 새로 만들어지는 클래스가 자식 클래스, 상속하는 클래스가 부모 클래스가 된다. 자바스크립트에서 상속은 extends를 쓴다.

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;
        }
}

var kim = new PersonPlus('kim',10,20);
console.log("kim.sum()",kim.sum()); //kim.sum() 30
console.log("kim.avg()",kim.avg());  //kim.avg() 15

PersonPlus 클래스에 sum()메서드가 없음에도 불구하고 kim 객체에 sum()을 호출하니 에러없이 결과값이 나왔다. 이는 PersonPlus의 부모 클래스 Person의 sum()메서드를 사용한 것이다. 약간 옆길로 새서 만약 Person과 PersonPlus 모두 sum()이 있었다면 PersonPlus 클래스의 sum()을 사용한다. 부모 클래스와 같은 함수명을 새로 정의하는 것을 오버라이딩이라고 한다.

 

2. super

클래스를 생성할 때, 부모 클래스의 기능을 활용해서 메서드나 변수를 선언하고 싶다면 super를 사용하면 된다.

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){
    	super(name,first,second);
        this.third = third;
    }
    
    sum(){
    	return super.sum() + this.third;
    }
    
    avg(){
    	return (super.sum() + this.third)/3;
    }
}

var kim = new PersonPlus('kim',10,20,30);
console.log("kim.sum()", kim.sum());  //kim.sum() 60
console.log("kim.avg()", kim.avg()); //kim.avg() 20

 PersonPlus constructor에 super()를 사용해서 Person constructor에 선언된 name,first,second 변수를 가져다 썼으며, 정의되지 않은 third는 새로 선언했다. 그리고 sum()과 avg메서드에서는 Person sum()메서드를 활용해서 함수를 정의하고 있다. 

 

3. object 상속

중괄호{}로 표현하는 object도 상속이 가능하다.

var superObj = {superVal:'super'};

//case1
var subObj = {subVal:'sub'};
subObj.__proto__ = superObj;

//case2
var subObj = Object.create(superObj);

//공통
subObj.subVal = 'sub';
console.log('subObj.subVal =>', subObj.subVal); //subObj.subVal => sub
console.log('subObj.superVal =>', subObj.superVal); //subObj.superVal => super
subObj.superVal = 'sub';
console.log('superObj.superVal =>', superObj.superVal); //superObj.superVal => super


case1과 case2의 결과값은 같다. superObj객체에는 superVal, subObj 객체에는 subVal이 있는데 상속을 통해 subObj에서도 superVal을 호출할 수 있었다. 단 subObj에서 superVal 값을 변경했을 때 subObj에서만 변경될 뿐, 참조하고 있는 SuperObj의 값은 변하지 않는다.

 

4. __proto__ vs prototype

객체가 생성될 때 객체가 참조하는 prototype 타입 객체도 함께 생성된다. 객체의 __proto__는 prototype 객체를 참조하고, prototype 객체의 constructor 프로퍼티는 생성된 객체를 참조한다.

즉 서로가 서로를 참조하는 것이다.