【问题标题】:Help with building object model帮助构建对象模型
【发布时间】:2011-09-21 21:55:05
【问题描述】:

请帮我建立对象模型。

我需要抽象类Unit 代表游戏中的每个军事单位。有SoldierTankJetBunker(单位的孩子)。他们每个人都有int属性CountDefense,带有单个int count参数的构造函数和一个方法GetTotalDefense

我的想法如下。

private abstract class Unit
{
    private int Count { get; set; }
    private const int Defense = 0;

    protected Unit(int count)
    {
        Count = count;
    }

    public int GetTotalDefense()
    {
        return Count * Defense;
    }
}

private class Tank : Unit
{
    private const int Defense = 5;
}

每个单元有不同的Count和不同的Defense。构造函数的主体和GetTotalDefense 的主体始终相同。 我需要的是在子类中覆盖Defense,因为每个单元都有不同的。此属性应为 const,所有 Tank (Soldier, ...) 实例具有相同的防御。是否有可能继承 const 属性或者每个孩子都需要自己的 const Defense 属性?

这是我想要实现的示例。

哦,还有部队类

public class Troop
{
    private Soldier Soldiers { get; set; }
    private Tank Tanks { get; set; }
    private Jet Jets { get; set; }
    private Fort Forts { get; set; }

    public Troop(int soldiers, int tanks, int jets, int forts)
    {
        Soldiers = new Soldier(soldiers);
        Tanks = new Tank(tanks);
        Jets = new Jet(jets);
        Forts = new Fort(forts);
    }

    public int GetTotalDefense()
    {
        return Soldiers.GetTotalDefense() + Tanks.GetTotalDefense() + Jets.GetTotalDefense() + Forts.GetTotalDefense();
    }
}

另外,欢迎提出更好的解决方案,谢谢。

PS:我对访问修饰符非常严格,所以你的例子要准确,谢谢。

【问题讨论】:

  • 如果每个访问修饰符上都有get; set;,为什么还要严格控制访问修饰符?
  • 请解释一下。什么时候是私有的,不需要get;设置;?
  • 我认为glowcoder他说如果你有一个属性的get和set,你可以在那里进行验证,那么为什么你需要严格呢?你也知道你可以做public int Count {get; private set;}吗?获取公开可读、可私写的属性?

标签: c# oop inheritance abstract-class


【解决方案1】:

你不能真正使用 const 但你可以创建一个只读属性,你确定你希望这些类是私有的而不是内部的或公共的吗?

public abstract class Unit { 

    protected Unit(int count) {
      Count=count;
    }

    protected int Count { get; private set; }
    protected abstract int Defense {get;}

    public int TotalDefense {
      get { return Count*Defense; }
    }

}

public class Tank : Unit {

   public Tank(int count) : base(count) {}

   protected override int Defense {
     get { return 5; }
   }
}

public class Troop {

   private Unit[] Troops;

   public Troop(int soldiers, int tanks, int jets, int forts) {
     Troops = new Unit[] {
                new Soldier(soldiers),
                new Tank(tanks),
                new Jet(jets),
                new Fort(forts)
              };
   }

   // The using System.Linq you can do
   public int TotalDefense {
     get { return Troops.Sum(x=>x.TotalDefense);}
   }
}

【讨论】:

  • 我不需要它们是公开的,我也不知道内部修饰符,所以私人是我的选择:)
  • 不工作的选择:D 是internal 解决方案,用于禁用从另一个命名空间访问类吗?
  • 顺便说一句,使用属性而不是方法更好吗?这是为什么?我说的是Troop 类中的TotalDefense 属性。
  • @Andrew private 意味着只有类本身可以访问它,protected 意味着只有类和从它继承的项目,internal 意味着只有同一个程序集中的项目。
  • @Andrew 来自microsoft guidelines,您应该对数据使用属性,对操作使用方法。此外,如果您曾经使用 WPF 绑定(我知道您的游戏不太可能使用它!),那么您不能绑定到方法,但可以绑定到属性。
【解决方案2】:

这个方案虽然没有使用const,但是达到了你想要的效果:

internal abstract class Unit
{
    private int Count { get; set; }
    private int Defense { get; set; }
    public int TotalDefense { get { return Count * Defense; } }

    protected Unit(int defense, int count)
    {
        Defense = defense;
        Count = count;
    }
}

internal class Tank : Unit
{
    protected Tank(int count)
        : base(5, count)  // you can use a const variable instead of 5
    {
    }
}

或许这样更合适:

internal abstract class Unit 
{ 
    private int Count { get; set; } 
    public abstract int Defense { get; }
    public int TotalDefense { get { return Count * Defense; } }

    protected Unit(int count) 
    { 
        Count = count;
    }
} 

internal class Tank : Unit 
{
    override public int Defense { get { return 5; } }

    protected Tank(int count) : base(count)
    {
    } 
}

【讨论】:

    【解决方案3】:

    您要查找的实际上是readonly。另外,由于Defense 在子类中使用,您需要对其进行保护。

    private abstract class Unit  
    {  
        private int _Count;  
        protected readonly const int Defense;
    
        public int TotalDefense
        { get { return Count * Defense; } }
    
        protected Unit (int count, int defense)
        {
            Defense = defense;
            _Count = count;
        }
    }  
    
    private class Tank : Unit  
    {
        public Tank (int Count)
            : base (Count, 5)
        { }        
    }
    
    public class Troop
    {
        public IEnumerable<Unit> Units { get; protected set; }
    
        public Troop (int soldiers, int tanks, int jets, int forts)
        {
            Troops = new Unit[]
            {
                new Soldier (soldiers),
                new Tank (tanks),
                new Jet (jets),
                new Fort (forts)
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      可能是这样的(但这是在 java 中)

      abstract class Unit {
          Unit(int defense,int count) {
              this.defense = defense;
              this.count=count;
          }
          final int defense;
          int count;
      }
      class Soldier extends Unit {
          Soldier(int count) {
              super(1,count);
          }
      }
      class Tank extends Unit {
          Tank(int count) {
              super(5,count);
          }
      }
      public class Main {
          public static void main(String[] args) {
              Unit[] units = { new Soldier(2), new Tank(3) };
              for(Unit unit:units)
                  System.out.println(unit.count+" "+unit.defense);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-22
        • 2011-07-24
        • 1970-01-01
        • 2020-02-21
        • 1970-01-01
        • 2011-08-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多