OOP-Inheritance

Seungjae Han·2020년 9월 10일
0

Inheritance

Inheritance는 상속이라는 뜻으로 객체 지향 프로그래밍의 중요한 특징 중 하나다. Java나 C++과 같은 객체지향언어는 class를 상속해준다. Javascript도 ECMAScript6부터 class의 등장으로 가능하지만 프로토타입을 기반으로 한 Javascript만의 프로토타입 체인에 대해 먼저 알아보겠다. 그리고 나서 class로 인한 상속도 알아보겠다.

proto,Prototype프로퍼티

function A(){};
let obj = new A();
obj.__proto__ == A.prototype; // true

__proto__란 A가 가지고 있는 기능을 obj안에 상속시키는 역할을 한다. 즉 어떤 객체가 만들어지기 위해 객체의 모태가 되는 것을 뜻한다.

let objA = {name : "Han", introduce : function(){console.log("Hello~"+this.name)}}
let objB = {name : "KiM"};

objB.__proto__ = objA;
let objC = {};
objC.__proto__ = objB;
objC.introduce(); //Hello~Kim
objA.introduce(); //Hello~Han
objB.introduce(); //Hello~Kim

__proto__ 에는 객체는 상위 함수의 prototype Object를 가르키고 있다고 보면 된다.
사진과 같이 objA안 프로토에는 상위 프로토타입인 Object가 존재하고 objB에는 objA가 존재하고 objC에는 objB가 존재한다.

이해가 힘들어 예시를 들며 연습해보겠다.

let f1 = function(name){
  this.name = name;
};

f1.prototype.f1Proto = function(){console.log("프로토타입")};

let obj = new f1("프로토");

obj.f1Proto() //"프로토타입"
obj.__proto__ == f1.prototype //true
obj.__prpto__ // {f1Proto: ƒ, constructor: ƒ}
f1.prototype //{f1Proto: ƒ, constructor: ƒ}

f1의 프로토타입 속 메소드를 만들어주는 과정이다. obj는 이 f1을 new 연산자를 통해 생성된다. 이렇게 생성이 이루어졌을때 obj의 __proto__는 f1의 프로토타입이다. obj에서는 이 함수를 바로 사용할 수 있다. f1의 프로토타입에서 생성된 매소드는 obj에서 바로 사용이 가능한 것 이다.

Constructor프로퍼티

함수를 정의하면 함수 객체는 기본적으로 prototype 프로퍼티를 갖게 된다. prototype프로퍼티는 프로토타입 객체를 가리키며, 프로토타입 객체는 기본적으로 constructor프로퍼티와 내부 프로퍼티(__proto__)를 가지고 있다.

function F() {};
F.prototype.constructor; //ƒ F(){}

constructor프로퍼티는 함수 객체의 참조를 값으로 받는다.

생성된 함수의 내부프로퍼티는 기본적으로 Object.prototype을 가르킨다.

F.prototype.__proto__


정리를 해보자면 함수 F의 인스턴스인 obj의 __proto__는 F.prototype을 가르키고 F.prototype의 __proto__는 Object.prototype을 가르킨다.

만약 인스턴스 생성 후에 생성자의 프로토타입을 수정하거나 교체가 필요한 경우는 어떻게 해야될까?

function Add(X,Y){
  this.X = X;
  this.Y = Y;
}
let add = new Add(3,4);
Add.prototype = {
  constructor : Add,
  plus: function(){return this.X+this.Y}
};
add.plus(); // Uncaught TypeError : add.plus is not a function

왜 이런 결과가 나올까 prototype 프로퍼티를 통째로 바꿔줬음에도 불구하고 실행이 되지 않는다. 이유는 생성자의 prototype 프로퍼티를 다른 객체로 교체해도 인스턴스의 프로토타입은 바뀌지 않기 때문이다. 인스턴스의 프로퍼티는 생성되는 시점에서 생성자의 프로토타입에서 상속을 받게 됩니다. 하지만 새로운 객체를 만들어주는 것이 아닌 기존의 prototype프로퍼티에 메소드를 추가하게 되면 인스턴스에도 추가가 됩니다.

function Add(X,Y){
  this.X = X;
  this.Y = Y;
}
let add = new Add(3,4);
Add.prototype.plus = function(){return this.X+this.Y}
add.plus(); //7

Add라는 생성자에 새로운 메소드를 추가해주는 방식에 대해 알아보았다. 그렇다면 이런 prototype을 이용해 oop를 할 수 있을까? 이는 object create 를 정리한뒤 설명하겠다.

Object.prototype

위에서 살펴보면 모든 함수의 prototype.__proto__는 Object.prototype과 똑같았습니다. 다시말해 F는 Object의 인스턴스이다. 이런 Object는 어떤 기능을 가지고 있을까?

Object()

let obj = new Object();
obj // {}
let obj1 = {}
obj1 //{}

Object() 생성자는 객체 리터럴로 작성한 빈 객체와 같은 결과를 내놓는다.

Object.create로 객체생성

let person1 = {name : "Han" , 
               introduce : function() {console.log("My name is " + this.name)}
              };
let person2 = Object.create(person1);
person2 // {}
person2.name = "Kim"; // {name: "Kim"}
person2.introduce();//My name is Kim

person2.__proto__ == person1; //true
person1.proto == Object.prototype //true

Object.create를 이용해서 객체를 생성하는 방법중 입력 값에 객체를 넣으면 만들어진 객체의 __proto__는 괄호안 객체와 같은 것으로 확인이 된다. 그래서 person2에 .name을 넣어 바꾸고 person1 안에 있는 메소드도 사용하고 이런 기능이 되는것이다. 그렇다면 괄호에 함수를 넣으면 어떻게 될까?

function F(){};

let obj = new Object(F);
obj === F //true

같은 함수를 obj에 생성하게 한다.
create에 대해서 좀 더 자세히 알아보겠다.

profile
공부하는 개발자 재밌게 일하고 싶습니다.

0개의 댓글