【问题标题】:C# and a proper way of inheritence [closed]C#和正确的继承方式[关闭]
【发布时间】:2020-03-20 22:12:19
【问题描述】:

我正在开发一款小型太空游戏。 那里需要许多可以建造的建筑物。 我不认为我的继承想法是正确的或有用的,我正在寻找一种在建造建筑物之前检查资源的好方法。如果我打算使用 15 个以上的资源,我不想检查每个建筑物的所有资源。 到目前为止,这是我对建筑物的想法。 如果有任何帮助,我将不胜感激!

namespace Space_Colony.Buildings
{
    class Building
    {
        String name = "undefined";
        int energyNeeded = 100000;
        int energyProduced = -100000;
        int buildTime = 100000;
    }

    class Solar_Panel_Weak : Building
    {
        String name = "Weak Solar Panel";
        int energyNeeded = 0;
        int energyProduced = 3;
        int buildTime = 20;

        int res_Needed_Wood = 10;
        int res_Needed_Iron = 10;
        int res_Needed_Sand = 10;
        int res_Needed_Electronics = 10;
    }

    class Landing_Field : Building
    {
        String name = "Landing Field";
        int energyNeeded = 0;
        int energyProduced = 0;
        int buildTime = 20;

        int res_Needed_Wood = 10;
        int res_Needed_Concrete = 10;
        int res_Needed_Color = 10;
    }
}```

【问题讨论】:

    标签: c# inheritance logic


    【解决方案1】:

    在您当前的代码中,子类的属性与基类的属性完全不同。您应该更改属性的访问修饰符,以便它们可用于子类。您可能还希望 Building 类是抽象的,因此您无法实例化它。

    abstract class Building
    {
        protected String name = "undefined";
        protected int energyNeeded = 100000;
        protected int energyProduced = -100000;
        protected int buildTime = 100000;
    }
    
    class Solar_Panel_Weak : Building
    {
        int res_Needed_Wood = 10;
        int res_Needed_Iron = 10;
        int res_Needed_Sand = 10;
        int res_Needed_Electronics = 10;
    
        public Solar_Panel_Weak()
        {
            name = "Weak Solar Panel";
            energyNeeded = 0;
            energyProduced = 3;
            buildTime = 20;
        }
    }
    

    【讨论】:

      【解决方案2】:

      @danielm 很好地说明了您的模型的继承,但我担心您的子类可能会失控。

      假设您有一个 Settlement 类,该类负责构建您定义的建筑物。例如,每个建筑物所需的资源并未以有意义的方式进行映射以制定通用解决方案。

      public class Settlement
      {
          ...
          public void Build(Building building, Inventory inventory)
          {
              if (building is Solar_Panel_Weak spw)
              {
                  // I've omitted validation for brevity
                  inventory.UseResource("Wood", spw.res_Needed_Wood);
                  inventory.UseResource("Iron", spw.res_Needed_Iron);
                  inventory.UseResource("Sand", spw.res_Needed_Sand);
                  inventory.UseResource("Electronics", spw.res_Needed_Electronics);
              }
              else if (building is Landing_Field lf)
              {
                  // I've omitted validation for brevity
                  inventory.UseResource("Wood", spw.res_Needed_Wood);
                  inventory.UseResource("Concrete", spw.res_Needed_Concrete);
                  inventory.UseResource("Color", spw.res_Needed_Color);
              }
              // So on...
          }
      }
      

      会有很多重复的代码,需要修改代码中的多个地方才能添加新的建筑。

      如果您决定让子类处理构建,则会出现类似的问题,因为处理所需资源的方式将要求每个子类实现 Build 方法。

      通过重组您的班级以接受材料列表,例如:

      public class Material
      {
          public string Name { get; set; }
          public int QtyRequired { get; set; }
      }
      
      public abstract class Building
      {
          public IEnumerable<Material> MaterialsRequired = new List<Material>();
      
          public string Name { get; set; }
          public int BuildTime { get; set; }
          public int EnergyNeeded { get; set; }
          public int EnergyProduced { get; set; }
      
          public Building(string name, int buildTime, int energyNeeded, int energyProduced)
          {
              Name = name;
              BuildTime = buildTime;
              EnergyNeeded = energyNeeded;
              EnergyProduced = energyProduced;
          }
      }
      
      public class SolarPanels : Building
      {
          public SolarPanels() : base("Solar Panel", 20, 0, 3)
          {
              MaterialsRequired = new List<Material>
              {
                  new Material { Name = "Wood", QtyRequired = 10 },
                  new Material { Name = "Iron", QtyRequired = 10 },
                  new Material { Name = "Sand", QtyRequired = 10 },
                  new Material { Name = "Electronics", QtyRequired = 10 },
              };
          }
      }
      

      我们可以使用更通用的方法来解决构建问题,例如:

      public class Settlement
      {
          ...
          public void Build(Building building, Inventory inventory)
          {
              foreach (var material in building.MaterialsRequired)
              {
                  if (inventory.HasRequiredMaterials(material))
                  {
                      inventory.UseResource(material);
                  }
              }
          }
      }
      

      使用这种方法,负责建造建筑物的班级不必费力地考虑建造建筑物。我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-19
        • 2013-05-02
        • 2014-07-13
        • 2012-04-11
        • 1970-01-01
        • 1970-01-01
        • 2017-08-20
        相关资源
        最近更新 更多