2014-12-16 4 views
0

enter image description hereкак реализовать паразитический наследование, чтобы избежать гнездования

Я хотел бы следовать структуре наследования, показанной выше. Я хотел бы создать инженер, используя следующий синтаксис:

Для достижения этого синтаксиса, я должен создать вложенный объект следующего паразитарного шаблона наследования как так:

function Employee(id) { 
     this.id = id; 

     this.WorkerBee = function(project) { 
     this.project = project; 

     this.Engineer = function() { 
      ... 
      return this; 
     }; 

     return this; 
     }; 
    } 

Чтобы избежать глубоких слоев вложенности , Я пытаюсь переписать его с использованием прототипов. Как я могу переписать свой код для достижения той же цели, что и выше?

 function Employee(id) { 
 
     //variables 
 
     this.id = id 
 
     this.name = ""; 
 
     this.dept = "general"; 
 

 
     //methods 
 
     this.getId = function() { 
 
      return this.id 
 
     } 
 
     } 
 
    Employee.prototype.WorkerBee = WorkerBee; 
 

 
    function WorkerBee(project) { 
 
     //variables 
 
     this.projectName = project 
 
     this.projects = []; 
 
     //methods 
 
     this.getProjectName = function() { 
 
     return this.projectName 
 
     } 
 
     return this 
 
    } 
 
    WorkerBee.prototype.Engineer = Engineer 
 

 
    function Engineer() { 
 
     //variables 
 
     this.dept = "engineering"; 
 
     this.machine = ""; 
 
     //methods 
 
     this.getDept = function() { 
 
     return this.dept 
 
     } 
 
     return this 
 
    } 
 

 
    var Mark = new Employee("5").WorkerBee("Secret Project").Engineer(); 
 
    console.log(Mark.getId()) //should print "5" 
 
    console.log(Mark.getProjectName()) //should print "Secret Project" 
 
    console.log(Mark.getDept()) //should print engineering

+0

* «Мне нужно создать вложенный объект после паразитного шаблона наследования, например, так» * Не обязательно, разумно уверен, что существуют более простые способы. Обязательно ли вы хотите использовать конструкторские функции для создания объектов, или вы довольны более прямыми формами прототипического наследования? –

+2

* «Я хотел бы создать инженера, используя этот синтаксис: var Mark = new Employee (id) .WorkerBee (project) .Engineer();' "* ** Почему? ** Это чрезвычайно запутанно. Почему бы нет: 'var Mark = new Engineer (id, project);'? Это будет * значительно более стандартным, а также очень простым в реализации. –

+0

*** вздох *** Еще один вопрос. –

ответ

0

UPDATE:

Хорошо, я отчасти понимаю. В чем причина, почему вы хотите это сделать? Вам просто нужен ярлык для создания нескольких экземпляров с использованием нескольких операторов?

Если экземпляр C возвращаемый A().B().C() быть иначе, чем тот, созданный со стандартным new C()?

Если вы хотите просто построить конструкторы, вы можете добавить контекст, в котором они определены (скорее всего, глобальный объект) в цепочку прототипов созданных объектов. Вы должны быть в состоянии сделать это:

var A = function() {}; 
A.prototype = Object.create(this); 

Что это не устраняет, хотя это необходимо для new ключевого слова для конкретизации. Вам нужно будет сделать new (new (new A()).B()).C(). Я не могу думать о другом подходе, чем иметь вспомогательную функцию, которая будет создавать конструктор, которые не требуют new ключевого слова:

var define = function (init) { 
    var Constructor = function() { 
    if (!(this instanceof Constructor)) { 
     return new Constructor(); 
    } 
    if (init) { 
     init.apply(this, Array.prototype.slice.call(arguments)); 
    } 
    }; 
    Constructor.prototype = Object.create(this); 
    return Constructor; 
}; 

употреблено:

var A = define(function (x, y) { 
    this.x = x; 
    this.y = y; 
}); 

var a1 = new A(1, 2); 
// a1 instanceof A === true 
// a1.x === 1 
// a1.y === 2 

var a2 = A(1, 2); 
// a2 instanceof A === true 
// a2.x === 1 
// a2.y === 2 

Если у вас есть конструкторы A , B и C, вы можете использовать следующие обозначения взаимозаменяемы:

var a = new A(); 
var b = new B(); 
var c = new C(); 

var a = A(); 
var b = B(); 
var c = C(); 

var b = A().B(); 
var c = A().C(); 

var a = B().C().A(); 

В случае A().B().C(), у вас нет доступа к экземплярам A и B.

Можете ли вы подробнее рассказать о своей сделке?


OLD ОТВЕТ:

То, что вы есть безумие, как вы в основном объединить три конструктора и сделать это, кажется, что `` WorkerBee` и Employee` фактически экземпляры в то время как они не являются.

Я не стану подвергать сомнению нотацию new A().B().C(), хотя я нахожу ее довольно перепутанной.

Возможно, вы пользуетесь оператором instanceof следующим образом.

var A = function (x) { 
    if (!(this instanceof A)) return new A(x); 

    this.x = x; 
}; 

var B = function (y) { 
    if (!(this instanceof B)) return new B(y); 

    this.y = y; 
}; 

var C = function() { 
    if (!(this instanceof C)) return new C(); 
}; 

A.prototype.B = B; 
B.prototype.C = C; 

Теперь вы можете позвонить new A() и A(), new B() и B() и new C() и C() взаимозаменяемы, получая тот же результат, как и из вызовов всегда возвращает экземпляр конструктора.

new A() instanceof A === true 
new A().B() instanceof B === true 
new A().B().C() instanceof C === true 
+0

Привет, Ян, я просто использую приведенный выше код в качестве примера. Я знаю, что лучший способ создать Engineer будет var Mark = new Engineer(), однако у меня есть код, который следует за шаблоном Object(). Object(). Method() и этот пример - просто ясный способ передать его , – Paolo

+0

См. Мое обновление выше. –

0

На основе комментариев, вы, кажется, есть мнение, что вы должны использовать этот странный, подробный механизм для того, чтобы иметь удела между Работником < - WorkerBee < - инженер (и такие), но вы не «т; нормальное наследование все, что нужно для этого:

// ==== Employee 
 
function Employee(id) { 
 
    this.id = id; 
 
} 
 
// Add Employee methods to Employee.prototype, e.g.: 
 
Employee.prototype.getId = function() { 
 
    return this.id; 
 
}; 
 

 
// ==== WorkerBee, derived from Employee 
 
function WorkerBee(id, project) { 
 
    // Inheritance, part 1: Chain to the base constructor 
 
    Employee.call(this, id); 
 

 
    // WorkerBee stuff 
 
    this.project = project; 
 
} 
 

 
// Inheritance, part 2: Create the object to use for WorkerBee 
 
// instance prototypes, using Employee.prototype as its prototype. 
 
WorkerBee.prototype = Object.create(Employee.prototype); 
 
WorkerBee.prototype.constructor = WorkerBee; 
 

 
// Add WorkerBee methods to WorkerBee.prototype, e.g.: 
 
WorkerBee.prototype.getProjectName = function() { 
 
    return this.project; 
 
}; 
 

 
// ==== Engineer, derived from WorkerBee 
 
function Engineer(id, project) { 
 
    // Inheritance, part 1: Chain to the base constructor 
 
    WorkerBee.call(this, id, project); 
 
} 
 

 
// Inheritance, part 2: Create the object to use for Engineer 
 
// instance prototypes, using WorkerBee.prototype as its prototype. 
 
Engineer.prototype = Object.create(WorkerBee.prototype); 
 
Engineer.prototype.constructor = Engineer; 
 

 
// Add Engineer methods to Engineer.prototype, e.g.: 
 
Engineer.prototype.getDept = function() { 
 
    return "Engineering"; 
 
}; 
 

 
// ==== Usage 
 
var mark = new Engineer("5", "Secret Project"); 
 
snippet.log(mark.getId());   // "5" 
 
snippet.log(mark.getProjectName()); // "Secret Project" 
 
snippet.log(mark.getDept());  // "Engineering"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Это стандартный способ сделать прототипичное наследование с помощью функции конструкторы в JavaScript (на данный момент, в ES6, вы бы использовать новую функцию class , который делает в основном то же самое, с некоторым синтаксическим сахаром). Просто добавьте Manager (производный от Employee) и SalesPerson (производный от WorkerBee).

На старых браузерах, возможно, потребуется частичное polyfill для Object.create, который выглядит следующим образом:

if (!Object.create) { 
    Object.create = function(proto, props) { 
     if (typeof props !== "undefined") { 
      throw "The two-argument version of Object.create cannot be polyfilled."; 
     } 
     function ctor() { } 
     ctor.prototype = proto; 
     return new ctor(); 
    }; 
} 

Есть transpilers для принятия источника ES6 с class и превратить его в ES5 код. Также есть мой сценарий Lineage, который делает наследование намного менее подробным.