【问题标题】:Using object inheritance when both objects pass arguments当两个对象都传递参数时使用对象继承
【发布时间】:2016-04-29 13:11:58
【问题描述】:

我有一个 Equipment 父类,它接受 args 和两个孩子 Weapon 和 Armor,它们也接受 args。我不确定是否有针对原型的特殊方法,或者我的代码是否真的不起作用,但这里是 shortened DEMO

我需要根据其他变量的值以及使用随机数的算法来创建用于每个对象中的参数的变量。每个项目都是独一无二的,所以我需要在制造武器伤害的同时为装备制造 hp,我不知道该怎么做。

function Equipment(hp) {
  var self = this;
  this.hp = hp;
}
//create subclass for weapons
function Weapon(baseDam) {
  var self = this;
  this.baseDam = baseDam;
}

function generateEquipment() {
  hp = Math.round(Math.random() * 10);
  baseDam = Math.round(Math.random() * 50);
  Weapon.prototype = new Equipment(hp);
  weapon = new Weapon(baseDam);
  stringed = JSON.stringify(weapon);
  alert(stringed);
}

generateEquipment();

【问题讨论】:

  • 能否请您多说一下您真正想要实现的目标?
  • 我编辑了我的问题,希望澄清
  • 越来越近 :) 如果方法称为“generateEquipment”,我不明白您为什么返回“武器”。您是否打算在此功能中创建其他“设备”?
  • @lipp 在游戏中是的,每次访问商店都会生成 6 件带有随机变量的装备。它有大约 35% 的机会成为武器,否则它将成为盔甲。

标签: javascript oop object inheritance


【解决方案1】:

首先,回答您的问题: 您的代码并没有真正错误,并且您的武器仍然有它的 hp,除了它包含在对象原型中,因此在字符串化时不会显示。 有一些方法可以解决这个问题,就像我展示的 here 一样,但在我看来这不是正确的方法。

通常,原型应该只存储方法而不是实例变量,因为如果你以后决定修改原型,实例变量也会被修改,以防它通过引用传递。

更好的模式是使用 Object.assign - 它最容易理解并且感觉最自然。此外,如果您希望 Weapon 是设备的子类,则该逻辑应封装在 Weapon 本身中。

这是声明武器类的建议新方法:

function Weapon(baseDam) {
  var self = this;
  var hp = Math.round(Math.random() * 10);
  Object.assign(self, Equipment.prototype, new Equipment(hp));
  this.baseDam = baseDam;
}

由于 hp 也是随机生成的,因此该逻辑现在封装在 Weapon 中。这也是可扩展的,因为这种模式也适用于长继承链。

有些人可能会推荐 ES6 类,这也是一种可行的方法,但在我看来,它是语法糖,它隐藏了代码的大部分内部工作。

Here 是我的方法的工作演示。

【讨论】:

  • 这当然是一个可行的答案,我唯一的问题是在我的实际代码中,它们大约有十个或更多的设备变量,我不想在函数中重复该代码武器和功能Armor,这也都需要通过localStorage,我不能通过localStorage中的功能
  • 您只需要获取所有公共变量并将它们放在父类中......所有武器特定和装甲特定变量都将进入它们各自的构造函数see here。至于 localStorage,我猜你想存储实例而不是构造函数,所以 localStorage.weapon1 = new Weapon(12); 可以正常工作。
  • 如果我理解正确的话,我只需要在 Weapon and Armor 中创建变量,而不是在 generateEquipment 函数中?
  • 是的,完全正确...所有实例变量都应该在构造函数中作为this.something = "something"
【解决方案2】:

您所描述的“模式”称为“组合”,可以非常强大。有许多不同的方法可以组合/组合新的类或对象。

阅读您的问题和 cmets,在我看来,您主要对定义许多不同类型的设备感兴趣,而无需太多(重复)代码。

您是否考虑过将一个类名数组传递给您的generateEquipment 方法并返回一个新的自定义构造函数?这是一个例子:

function Equipment(hp) {
  this.hp = Math.round(hp);
}

Equipment.prototype.describe = function() {
  return "This piece of equipment has " + this.hp + " hitpoints";
}

function Weapon(baseDam) {
  this.baseDam = Math.round(baseDam);
}

Weapon.prototype.describe = function() {
  return "The weapon does " + this.baseDam + " damage";
}

function generateCustomEquipment(types) {
  var CustomEquipment = function() {
    var self = this;

    // Create the properties for all types
    types.forEach(function(type) {
      type.call(self, Math.random() * 100);
    });
  };

  CustomEquipment.prototype.describe = function() {
    var self = this;

    // Combine the 'describe' methods of all composed types
    return types
      .map(function(type) {
        return type.prototype.describe.call(self);
      })
      .join(". ");
  }

  return CustomEquipment;
}

var Sword = generateCustomEquipment([Equipment, Weapon]);
var Armor = generateCustomEquipment([Equipment]);
var Arrow = generateCustomEquipment([Weapon]);

var sword1 = new Sword();
document.writeln("A sword: " + sword1.describe() + "<br/>");

var armor1 = new Armor();
document.writeln("A piece of armor: " + armor1.describe() + "<br/>");

var arrow1 = new Arrow();
document.writeln("An arrow: " + arrow1.describe() + "<br/>");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 2016-03-26
    • 1970-01-01
    相关资源
    最近更新 更多