Есть ли способ установить поле в области дочерних объектов, будучи доступным из родительского объекта? - PullRequest
0 голосов
/ 08 сентября 2011

У меня есть опыт работы с ООП в JavaScript. Моя цель - иметь родительский объект, который содержит методы, общие для нескольких других объектов, которые наследуются от этого родительского объекта. Дело в том, что я хочу, чтобы методы родительских объектов могли читать дочерние поля.

Я использую следующую функцию для наследования:

Function.prototype.inherits=function(obj){this.prototype=new obj();}

Вот несколько примеров объектов:

function Genetic(c){
    this.code=c;
}
//My 'parent object':
function Animal(){
    this.getCode=function(){
        return(genetic.code);
    }
}
g=new Genetic('test');
function Dog(){
    genetic=g;
}
Dog.inherits(Animal);
g=new Genetic('foo');
function Cat(){
    genetic=g;
}
Cat.inherits(Animal);

d=new Dog();
c=new Cat();

Теперь я ожидаю, что d.getCode() вернет 'test', а c.getCode() вернет 'foo'. Проблема в том, что оба возвращают 'foo'. Переменная genetic находится в области действия Animal, а не в области действия Dog / Cat. Это означает, что всякий раз, когда я создаю новый объект, который наследуется от Animal, переменная genetic будет переопределена. Доказательство:

function Bla(){}
Bla.inherits(Animal);
bla=new Bla()
bla.getCode() //Returns 'foo'

Я могу установить переменную genetic в качестве закрытой переменной Dog и Cat с помощью var:

function Dog(){
    var genetic=g;
}

Проблема в том, что genetic теперь является приватным для Dog, объект Animal не может получить к нему доступ, что делает все наследство бессмысленным.

Видите ли вы какой-нибудь способ решить это?

EDIT: Кроме того, я хочу, чтобы gentic был приватным, чтобы его нельзя было изменить в Dog / Cat экземплярах.

1 Ответ

3 голосов
/ 08 сентября 2011

Переменная «генетическая» находится в области «Животное», а не в области «Собака / кошка».

Нет, genetic - это global . Во всем приложении существует только одна переменная genetic. Сделайте это свойством объекта.

Кроме того, лучшим способом наследования является следующий:

function inherits(Child, Parent) {
    var Tmp = function(){};
    TMP.prototype = Parent.prototype;
    Child.prototype = new Tmp();
    Child.prototype.constructor = Child;
}

Тогда родительский конструктор может принимать аргументы и не должен повторять код:

//My 'parent object':
function Animal(g){
    this.genetic = g;
}

Animal.prototype.getCode = function() {
    return this.genetic.code;
}

function Dog(){
    Animal.apply(this, arguments);
}
inherits(Dog, Animal);

function Cat(){
    Animal.apply(this, arguments);
}
inherits(Cat, Animal);

var d = new Dog(new Genetic('test'));
var c = new Cat(new Genetic('foo'));

Я бы посоветовал правильно документировать ваш код и скорее следовать четкой цепочке прототипов / наследования, чем пытаться делать что-то, для чего язык не предназначен.

Однако, с помощью функции inherits, указанной выше, вы можете сделать:

function Animal(g){
    var genetic = g

    this.getCode = function(){
        return genetic.code ;
    }
}

, а остальная часть кода остается прежней. Тогда у вас есть ваша «приватная» переменная за счет каждого экземпляра, имеющего собственную функцию getCode.

Редактировать: Это не позволит вам получить доступ к genetic в любой функции, назначенной Dog или Cat, если только вы не сохраните ссылку на значение в их конструкторах.

...