2013-05-30 2 views
3

저는 자바 스크립트 기술을 새로 고쳐서 객체가 다른 것으로부터 상속받을 수있는 방법을 생각해 냈습니다. 상속은 나무와 비슷해야합니다.javascript multilevel inheritance 이상한 결과

Parent->Child->Child2

나는 확장 한 Function.prototype (이,이 나중에 변경 될 수 있습니다 나쁜 생각 말하지 마)

Function.prototype.extend = function(child) 
{ 
    // save child prototype 
    var childPrototype = child.prototype; 
    // copy parent to child prototype 
    child.prototype = Object.create(this.prototype); 
    // merge child prototype 
    for (var property in childPrototype) { 
     child.prototype[property] = childPrototype[property]; 
    } 
    child.prototype.constructor = child; 
    child.prototype.$parent = this.prototype; 
    return child; 
}; 

부모 개체 :

var Parent = (function() 
{ 
    var Parent = function(x, y) 
    { 
     this.x = x; 
     this.y = y; 
     console.log('Parent constr', x, y); 
    } 

    Parent.prototype.move = function(x, y) 
    { 
     this.x += x; 
     this.y += y; 
     console.log('Parent moved.'); 
    }; 

    return Parent; 

}()); 

첫 번째 아이 :

var Child = Parent.extend(function() 
{ 
    var Child = function(x, y) 
    { 
     this.$parent.constructor(x, y); 
     console.log('Child constr'); 
    } 

    Child.prototype.print = function() 
    { 
     console.log('Child print', this.x, this.y); 
    }; 

    // override 
    Child.prototype.move = function(x, y) 
    { 
     this.$parent.move(x, y); 
     console.log('Child moved.'); 
    }; 

    return Child; 

}()); 

둘째 아이 :

var Child2 = Child.extend(function() 
{ 
    var Child2 = function(x, y) 
    { 
     this.$parent.constructor(x, y); 
     console.log('Child2 constr'); 
    } 

    // override 
    Child2.prototype.move = function(x, y) 
    { 
     this.$parent.move(x, y); // call parent move 
     console.log('Child2 moved.'); 
    }; 

    return Child2; 

}()); 

지금까지 너무 좋아. 부모 생성자와 메서드를 호출하고 메서드를 재정의 할 수도 있습니다.

var child = new Child2(1, 1); 
child.move(1, 1); 
child.print(); 

내가 올바른 출력 다음 얻을 :

Parent constr 1 1 
Child constr 
Child2 constr 
Parent moved. 
Child moved. 
Child2 moved. 
Child print 2 2 

을하지만 둘째 아이의 재정을 주석 만약 내가 다음 얻을 출력 :

Parent constr 1 1 
Child constr 
Child2 constr 
Parent moved. 
Child moved. 
Child moved. -> WHY?? 
Child print 2 2 

나는 이유를 이해하지 않습니다 Child moved.이 두 번 출력됩니다. 결과는 정확하지만 이상한 일이 일어나고 있습니다.

편집 :

마지막으로 더 나는 좋은 솔루션과 함께 제공되는 문제로 연구하고 다이빙 후 : 내가 다른 확장했다

// call method from parent object 
Object.getPrototypeOf(Child2.prototype).move.apply(this, arguments); 

Function에 : 다음

Function.prototype.getParent = function() 
{ 
    return Object.getPrototypeOf(this.prototype); 
}; 

그리고에 대한 예 : Child2 이동 방법 :

Child2.prototype.move = function(x, y) 
{   
    Child2.getParent().move.call(this, x, y); 
}; 

그래서 더 이상 $parent이 필요 없으며 원하는 결과를 얻습니다.

또 다른 해결책은 바로 부모의 프로토 타입을 호출하는 것입니다 :

Child2.prototype.move = function(x, y) 
{   
    Child.prototype.move.call(this, x, y); 
}; 
+0

다중 레벨 상속은 다중이 아닙니다. – C5H8NNaO4

+0

감사합니다. 제목을 편집했습니다. – bitWorking

+0

정확히 어떤 부분을 "주석 처리 해제 하시겠습니까?" 내가 주석으로 처리 된 코드는 없다. – apsillers

답변

1

부모가 안전하지 못하도록 액세스하려면 this을 사용하여 올바른 범위에서 함수를 호출하려면 apply를 사용해야합니다. 이것은 실제로 JS 디버깅에 대해 배우기위한 훌륭한 문제입니다. 중단 점을 사용하여 모든 일이 발생하는 것을 볼 수 있습니다.

// override 
Child.prototype.move = function(x, y) 
{ 
    this.$parent.move(x, y); 
    console.log('Child moved.'); 
}; 

이 코드는 childchild.move(1,1), this 점을 호출하여 도달하면 무엇합니까 child.$parent.move 점 :

첫 번째 자식을보고? 왜, 물론 첫 번째 하위 구현!

두 번째로, this은 부모의 프로토 타입을 가리키며 이제는 괜찮습니다.

그래서 이 무엇입니까?이 이유는 무엇입니까? 글쎄 그건 당신에게 달렸습니다. 기본 생각 이었기 때문에 적용을 언급 했으므로 this.$parent.move.apply(this, arguments);을 사용했지만, 은 실제로으로 상위 부모에게 액세스 할 수 없으므로 내가 생각할 수있는 유일한 다른 옵션은 binding (히치링 , dojo people reading) 모든 함수가 프로토 타입이기 때문에 항상 this 값이 항상 동일한 것을 가리키고, 따라서 항상 $ parent에 항상 액세스 할 수 있습니다.

물론 이것은 실제 개체 인스턴스에 액세스 할 수 없으므로 순수 유틸리티 기능에만 유용하지만 실제로는 새로운 것은 아닙니다. 개체 인스턴스의 x 및 y 멤버에 액세스하는 재정의 된 print를 사용하고 부모 호출을 시도하면 해당 인스턴스도 손상되었을 것입니다.

+0

나는 이것을'$ parent.move.call (this, x, y); '로 시도했지만 그것은 stackoverflow를 생성한다. – bitWorking

+0

예, 제가 말했듯이이 기술을 사용하면 인스턴스 객체에 액세스 할 수 있지만 상급 부모는 없으므로 한 수준의 상속 만 수행 할 수 있습니다. –

+0

감사합니다. 좋은 설명과 문제에 대한 해결책을 제시하는 답변을 수락합니다. 아직 찾지 못했습니다. – bitWorking

1

귀하의 확장 방법은 새 개체의 프로토 타입 상속 된 속성과 메서드를 연결합니다. 또한 부모 객체의 프로토 타입과 동일한 $ 부모 객체를 만듭니다. 이 결과는 중복됩니다. 당신이 재정을 주석하더라도

child.protoype.move 
child.$parent.move 
child.$parent.$parent.move 

(두 개의 동일한 기능에 대한 참조 있지만) 세 가지 이동 방법은 아직 없습니다 : 두 번째 아이는 세 가지 이동 방법이있다.

따라서 자식을 실행할 때.당신이 얻을 이동 :

child.prototype.move와 자식 $의 parent.move 두 번 실행되는 것을 방지하지 않습니다 동일한 기능을 모두 참조 것을 child.$parent.$parent.move

사실 호출 child.$parent.move 호출

child.prototype.move.을.