[Java Script] 객체지향 프로그래밍 : 상속

2021. 9. 14. 22:46CSE/Java Script

- 자바스크립트는 클래스를 기반으로 하는 전통적인 상속을 지원하지는 않음

=> 하지만 객체 프로토타입 체인을 이용하여 상속을 구현해낼 수 있다.

 

 

1. 프로토타입을 이용한 상속

(1) 상속

function create_object(o){
    function F() {}
    F.prototype = o;
    return new F();
}

- 위의 코드는 더글라스 크락포드가 자바스크립트 객체를 상속하는 방법으로 소개한 코드이다.

- create_object() 함수는 인자로 들어온 객체를 부모로 하는 자식 객체를 생성하여 반환한다.

=> 반환된 객체는 부모 객체의 프로퍼티에 접근할 수 있고, 자신만의 프로퍼티를 만들 수도 있다.

=> 이렇게 프로토타입의 특성을 활용하여 상속을 구현하는 것이 프로토타입 기반의 상속

 

- create_object() 함수는 Object.create() 함수로 제공되므로, 다음과 같이 사용하면 된다.

var person = {
    name : "zzoon",
    getName : function(){
        return this.name;
    },
    setName : function(arg){
        this.name = arg;
    }
};

function create_obejct(o){
    function F() {};
    F.prototype = o;
    return new F();
}

var student = create_obejct(person);

student.setName("me");
console.log(student.getName()); //me

 

 

(2) 상속을 받은 자식의 기능 확장 방법 : extend()

- 자식은 부모 객체의 메서드를 그대로 상속받아 사용하는 것 뿐만 아니라, 자신의 메서드를 재정의 혹은 추가로 기능을 더 확장시킬 수 있어야 한다.

- 자바스크립트에서는 범용적으로 extend()라는 함수로 객체에 자신이 원하는 객체 혹은 함수를 추가시킨다.

 

- jQuery 1.0의 extend 함수는 다음과 같다.

jQuery.extend = jQuery.fn.extend = function(obj,prop){
    if (!prop){ prop = obj; obj = this;}
    for (var i in prop) obj[i] = prop[i];
    return obj;
}

- jQuery.fn은 jQuery.prototype이다. 즉, jQuery 함수 객체와 jQuery 함수 객체의 인스턴스 모두 extend 함수가 있다.

- extend 함수의 인자가 하나만 들어오는 경우에는 this에 인자로 들어오는 객체의 프로퍼티를 복사하고, 두 개가 들어오는 경우에는 첫 번째 객체에 두 번째 객체의 프로퍼티를 복사한다.

- 이 코드에는 약점이 있다. 얕은 복사를 하기 때문에, 두 번째 객체의 프로퍼티가 변경되면 첫 번째 객체의 프로퍼티도 같이 변경된다.

- 깊은 복사로 extend 함수를 이용하고 싶으면, true를 파라미터로 넘겨주면 된다.

 

 

2. 클래스 기반의 상속

function Person(arg){
    this.name = arg;
}

Person.prototype.setName = function(value){
    this.name = value;
};

Person.prototype.getName = function(){
    return this.name;
};

function Student(arg){
}

var you = new Person("Iamhjoo");
Student.prototype = you;

var me = new Student("zzoon");
me.setName("zzoon");
console.log(me.getName()); //zzoon

- 위 코드에서 Student 함수 객체를 만들어서, 이 함수 객체의 프로토타입으로 하여금 Person 함수 객체의 인스턴스를 참조하게 만들었다.

=> 하지만, me 인스턴스를 생성할 때 부모 클래스인 Person의 생성자를 호출하지 않아, 인스턴스의 초기화가 제대로 이루어지지 않는다.

function Student(arg){
    Person.apply(this,arguments);
}

=> Student 함수에 위 코드를 추가하여 부모 클래스의 생성자를 호출해야 한다.

 

 

- 부모 클래스의 인스턴스와 자식 클래스의 인스턴스는 서로 독립적일 필요가 있다.

=> 두 클래스의 프로토타입 사이에 중개자를 하나 만들어보자.

function Person(arg){
    this.name = arg;
}

Function.prototype.method = function(name,func){
    this.prototype[name] = func;
}

Person.method("setName", function(value){
    this.name = value;
});

Person.method("getName", function(){
    return this.name;
});

function Student(arg){
}

function F() {};
F.prototype = Person.prototype;
Student.prototype = new F();
Student.prototype.constructor = Student;
Student.super = Person.prototype;

var me = new Student();
me.setName("zzoon");
console.log(me.getName());

- 빈 함수의 객체를 중간에 두어 Person의 인스턴스와 Student의 인스턴스를 서로 독립적으로 만들었다.

=> 스토얀 스테파노프는 위와 같은 상속 관계를 즉시 실행 함수와 클로저를 활용하여 최적화된 함수로 소개하였다.

var inherit = function(Parent,Child){
    var F = function() {};
    return function(Parent,Child){
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.prototype.constructor = Child;
        Child.super = Parent.prototype;
    };
}();