2010-02-17 2 views
0

을 일부 코드는 이상 천개의 단어를 말할 수 있습니다 :: 자바 스크립트 프로토 타입, 개인 회원, 상속

/** 
* Represents an amount of a resource 
* @param {number} amount 
* @param {string} type 
*/ 
function Resource(amount, type) 
{ 
    var nAmount = amount; 
    var sType = type; 

    if (amount < 0) 
    { 
     throw new IllegalArgumentException("amount has to be positive"); 
    } 

    /** 
    * @method Resource 
    * @return {number} amount of the resource 
    */ 
    this.getAmount = function() 
    { 
     return nAmount; 
    }; 

    /** 
    * @method Resource 
    * @return {string} resource type 
    */ 
    this.getType = function() 
    { 
     return sType; 
    }; 
} 

/** 
* Addition of two resources produces a new resource with the sum amount 
* the new object uses the old one as prototype 
* @param {Resource} resource 
* @return {Resource} new Resource object 
*/ 
Resource.prototype.plus = function(resource) 
{ 
    if (!(resource instanceof Resource && this.getType() == resource.getType())) 
    { 
     throw new IllegalArgumentException("resources don't match."); 
    } 

    var newRes = Object.create(this); // create a new object based on the current one 
    // execute the Resource constructor on it 
    Resource.call(newRes, this.getAmount() + resource.getAmount(), this.getType()); 
    return newRes; 
}; 

자원 객체는 불변으로 간주 ValueObjects 있습니다. 더하기 연산에서 새로운 객체를 반환합니다. 이제 "new Resource (args)"를 호출하여 반환 할 새 객체를 만드는 대신 이전 객체를 기반으로 새 객체를 만들었습니다. 이것은 또한 상속을 허용합니다.

모든 ValueObject에이 기능을 사용하기 시작 했으므로 (앞으로 어떤 시점에서 상속하고 싶을 경우를 대비하여) 조금 더 생각하게되었습니다.

JavaScript는 변경 불가능한 개체를 허용하지 않습니다. 그러나 개체는 직접 메서드 덮어 쓰기 또는 생성자 호출을 통해 취약합니다. 제가 할 수있는 건 이것들이 나쁜 습관이라고 결정하는 것뿐입니다. 안타깝게도 ECMAScript5의 "고정"은 아직 내 패턴이 호환되지만 그래도 아직 없습니다.

Object.recreate = function(proto, constructor, args) 
{ 
    var obj = Object.create(proto); 
    constructor.apply(obj, args); 
    return obj; 
}; 

및 그 : 이제이 코드 중복과 함께 불변의 객체에 생성자를 호출이 "나쁜 스타일"을 가지고

, 나는이 과정을 캡슐화하는 새로운 기능을 만들 생각 해요 :

Resource.prototype.plus = function(resource) 
{ 
    // if ... {throw ...} 
    return Object.recreate(this, Resource, 
      [this.getAmount() + resource.getAmount(), this.getType()]); 
}; 

누군가이 기능의 이름에 대해 더 좋은 아이디어를 가지고 있을지도 모릅니다. '재창조'는 내가 처음 생각한 것입니다. 이 패턴에 대해 어떻게 생각하세요? 그것은 과도한 추상입니까? 나는 이것을 내가 클래스에서 구해야 할 것인가? 내가 중요한 것을 놓친 건가?

편집 :이 기사에서 현재 반영되지 않은 중요한 내용을 언급하는 것을 잊어 버렸습니다. ValueObject는 Object.create로 쉽게 복제됩니다. 그들의 사적인 구성원은 변하지 않습니다. 그러나 변하기 쉬운 개인 회원은 어떨까요? 복제본에서 set()이 호출되면 클로저 내에 원본 프로토 타입 객체가 설정됩니다! 내 Object.recreate가 클로저를 다시 작성하면이 문제가 해결됩니다.

개인 변수를 사용하여 상속하는 더 좋은 방법이 있습니까? 왜 모두가 계급 창설을 위해 설탕을 사용합니까? 나는 prototypalism에 대해 많은 것을 읽었지 만, 나는 여전히 그것에 매달리지 않았다.

답변

0

지난 몇 년 후에이 코드가 나왔는데, 필자가 작성한 코드는 혼합 개념에 결함이 있다고 말할 수 있습니다. JavaScript는 closure에 의해 실제 private 변수를 실제로 제공 할 수 있습니다. ValueObjects는 어쨌든 변경할 수 없으므로 private 상태를 변경할 수 없으며 숨겨진 것들을 지나치게 복잡하게 만듭니다.

독창적 인 Object.recreate는 너무 추상적 인 "팩토리 메서드"의 일종으로, 필요한 경우 각 클래스에 대해 별도로 선언해야합니다.

상속을 통한 구성 사용! Crockford는 훌륭한 JavaScript 통찰력을 제공합니다. https://crockford.com/javascript/prototypal.html

0

필자는 복사 또는 복제가 더 나은 이름이라고 생각합니다. 이 article은 이러한 일반 기능을 만드는 메커니즘을 설명합니다.

+0

좋은 기사이지만, 나는 그다지 새로운 것을 얻을 수 없었습니다. owl.clone은 정확히 Object.create가 여기에 있으며, 그 이름이 더 잘 어울리는 것 같습니다. "Clone/create"와 충돌하는 개인 변수가있는 ValueObject가 아닌 경우에 대한 질문을 편집하겠습니다. 그러나 다시 만들지는 않습니다. – Phoscur