【问题标题】:Sharing parent property value with all derived children与所有派生子共享父属性值
【发布时间】:2016-02-29 22:15:43
【问题描述】:

假设有一个父类Shape和一个子类Rectangle。我想在子类中重用父类属性的值。

我可以在不重新初始化子类的情况下执行此操作吗(使用调用或应用)?

我希望所有子对象都使用相同的父属性值。

//Parent
function Shape(ctx) {
  this.context = ctx;
}
Shape.prototype.getContext = function() { return this.context; };

//Child - rectangle inherits from shape
function Rectangle(x,y,w,h) {
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;
}
//setup inheritance
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

Rectangle.prototype.draw = function() {
  //want to use inherited context here
  return this.context;
}

//create and run
var shape = new Shape("value");
var rectangle = new Rectangle(0,0,100,100);

//returns "value"
console.log( shape.getContext() );
//returns undefined - needing "value"
console.log( rectangle.draw() );

编辑 - 在下面的回复之后,我认为这就是我需要的。由于矩形实例不是从形状实例继承的,因此分配给形状的“值”不会传递给矩形。如何将其分配为 Shape 内部的默认值,然后在 Rectangle 构造函数中调用 Shape 构造函数。这允许我向所有子对象共享相同的上下文值,对吗?

附带问题,setter 不会影响 Shape 子级。所以我正在努力。

//Parent
function Shape() {
  this.context = "value";
}
Shape.prototype.getContext = function() { return this.context; };
Shape.prototype.setContext = function(x) { this.context = x; };

//Child - rectangle inherits from shape
function Rectangle(x,y,w,h) {
  Shape.call(this);
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;
}
//setup inheritance
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

Rectangle.prototype.draw = function() {
  //want to use inherited context here
  return this.context;
}

//create and run
var rectangle = new Rectangle(0,0,100,100);
//returns "value"
console.log( rectangle.draw() );

编辑 - 感谢回复,我认为下面正在完成我最初尝试做的事情。 Shape 父级以默认上下文值开头。 Shape 构造函数现在还接受一个参数,以防子类在最初调用时想要更改它。然后,每个子类都有一个用于上下文的 getter 和 setter,但除非更改,否则它将始终默认为初始 Parent 值。在深入研究之后,Shape 开始感觉像是一个抽象类或接口,但这与我最初的要求无关。

//Parent
function Shape(ctx) {
  this.context = (typeof ctx === "undefined") ? "default" : ctx;
}
Shape.prototype.getContext = function() { return this.context; };
Shape.prototype.setContext = function(x) { this.context = x; };

//Child - rectangle inherits from shape
function Rectangle(x,y,w,h) {
  //calls parent constructor
  Shape.call(this);
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;
}
//setup inheritance
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
//getter and setter - context defaults to parent value, but can be changed
Rectangle.prototype.getContext = function() { return this.context; };
Rectangle.prototype.setContext = function(x) { this.context = x; };
//other rectangle methods
Rectangle.prototype.draw = function() {
  return "doing something with " + this.context;
}

//create and run
var rectangle = new Rectangle(0,0,100,100);
//starts with Parent "default"
console.log( rectangle.getContext() );
//changes and uses different context
rectangle.setContext("different context");
console.log( rectangle.draw() );

【问题讨论】:

  • 您的rectangle 实例并非源自该shape 实例。

标签: javascript inheritance prototype


【解决方案1】:

我可以在不重新初始化子类的情况下执行此操作吗(使用调用或应用)?

不,没有办法调用你的超级构造函数。

请注意,这不是重新初始化属性,调用正在创建和初始化属性根本

我想在子类中重用父类属性的值。

这真的没有意义。该属性是实例的一部分,而不是类的一部分。如果您有多个子类,则没有父类的实例,只有子实例。如果您真的在创建父类的实例(如在您的示例代码中),那么这是一个单独的对象,与其他实例无关 - 大多数情况下,子对象不会以任何方式从该父实例派生.

【讨论】:

  • 谢谢@Bergi 我已经编辑了上面的代码。现在我正在尝试找到一种方法使父设置器适用于所有子对象...
  • 是的,更新后的代码似乎工作正常,为每个对象提供了具有相同值的属性。但是,我不明白您所说的“使父设置器适用于所有子对象”是什么意思? setter 总是只在单个实例上调用。听起来context 根本不应该是你的Rectangles 的属性,而是一个全局的——可能是静态属性或专用DrawingArea 类的属性?
  • 你说得对,我只是弄乱了 setter,从你的评论中我向子原型添加了一个 getter 和 setter,如果需要,应该在其中更改它(即在实例上,但对于所有其他孩子它会默认为 Parent 值)。
  • 您调用超类的指示帮助我获得了默认值,其他 cmets 也有所帮助,所以谢谢,我会选择您作为答案
【解决方案2】:

当你这样做来设置你的矩形时,返回值为undefined

//create and run
var shape = new Shape("value");
var rectangle = new Rectangle(0,0,100,100);

因为您实际上没有shape 连接到rectangle。您只创建了两个单独的 Shape 和 Rectangle 实例,除了共享某些结构之外,它们彼此之间没有任何关系。

有解决此问题的可能方案。在定义原型时,创建一个新的 Shape 以预先设置值。

//Use predefined Shape
var shape = new Shape("value");
Rectangle.prototype = shape;

现在,当使用前面显示的对draw 的调用时,value 将被返回并记录到控制台。

在我看来,这不是一个完整的场景,因为虽然您已经为上下文定义了一个 getter,但可能存在您希望更改它的场景。我还建议为上下文实现一个设置器,以便您可以根据需要注入不同的设置器。

【讨论】:

  • 您只能通过原型链中的公开方法到达那里” - 怎么样? this.context 怎么了?
  • 谢谢@TravisJ 我拿走了你的 cmets 并对问题进行了编辑。我试图让父值在子对象之间共享,所以我认为上面的编辑可以处理它,但是现在添加一个像你提到的 setter 似乎是一个问题(更改父值不会影响子对象) .
  • @ShawnMoore - 如您所示更改父值只会影响该实例的子级。您需要保留父实例以对其进行更改,以便所有派生实例仍仅引用一个父实例。要么,要么让它在这个设置之外的变量中。
  • @TravisJ 在对其进行了更多审查之后,让所有子对象都受到父对象更改的影响是个坏主意。我将保持 Parent 值的默认值,并且孩子们从它开始,除非它被故意设置为其他值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-14
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 2013-07-25
相关资源
最近更新 更多