【问题标题】:C# Inheritance of same class twiceC#继承同一类两次
【发布时间】:2015-09-30 00:20:14
【问题描述】:

假设我有这样的代码

public class Holded
{
    protected internal int holdedID = 0;
}

public class Inventory : Holded
{
    public Inventory() { }

    public void changeHoldedID()
    {
        this.holdedID = 100;
    }
}

public class Equipment : Holded
{
    public Equipment() { }

    public void writeHoldedID()
    {
        Console.WriteLine("Holded ID is: {0}!", this.holdedID);
    }
}

public class Cargo : Holded
{
    public Cargo() { }
}

如果我调用 changeHoldedID 然后 writeHoldedID,控制台仍会输出一个字符串,如“Holded ID is: 0!”。现在我想要实现的是在两个类中都有相同的基类(Holded)。因此,如果我从 Inventory 更改holdedID,Equipment 的 writeHoldedID 函数将输出“Holded ID is: 100!”。谢谢和问候!

@Edit:更详细:我有一个游戏。每个人都是一个角色,拥有设备、库存和货物类。每个类包含大约 20 个“项目”插槽。现在的问题是,如果你试图移动一个项目,例如。从库存到设备,并且有这样的物品索引,然后该物品被“交换” - 被持有,现在我可以将这种持有的物品放入设备,库存或货物中。这就是为什么我需要在 Eq/Inv/Cargo 之间共享此类。

【问题讨论】:

  • 听起来你只是想让 Holded 实现 2 个不同的接口,也许这是一个更好的方法?

标签: c# inheritance


【解决方案1】:

有了这种继承结构,你要问的问题 99.9% 是不可能的。

当您创建一个Inventory 对象时,您也在创建一个具有自己的holdedID 成员的Holded 对象。当您创建一个Equipment 对象时,您也会得到一个 Holded 对象,与旧对象没有关系。因此,对一个对象成员的更改不会影响另一个对象,您希望这样

*需要明确的是,在创建派生类时不会获得单独的 Holded 对象,但按照我描述的方式考虑它会有所帮助。

我不知道你为什么要按照你的要求去做,但这是一个很好的选择,你需要重新理解继承、对象和多态。

现在,我说这 99.9% 是不可能的。您可以标记基类成员static,它在Holded(和派生类)的所有实例之间共享它,从而使您的代码成为可能。 但是,您实际上几乎没有机会这样做static 只有在您了解面向对象设计以及使用它的后果时才应使用。

【讨论】:

  • 问题是每个人都需要一个库存和设备课程(我大约有 100 人)。所以在我的意思中 - 它不能是静态的。 Tho,我需要为每个库存/设备实现 Holded,因为 Holded 必须在这些类之间共享 - 以这种方式保持它对我来说更简单。现在,除了以“Holded”类作为参数初始化类并将此类类存储在变量中然后为库存/设备实现与 Holded 相关的相同功能之外,您是否还有其他方法可以摆脱这种情况?谢谢,问候。
  • @mexikanoZ 只能通过更详细的信息才能知道答案。例如,什么是“holdedId”?为什么需要在实例之间共享,为什么一个类设置,另一个类返回???
  • 更详细:我有一个游戏。每个人都是一个角色,拥有设备、库存和货物类。每个类包含大约 20 个“项目”插槽。现在的问题是,如果你试图移动一个项目,例如。从库存到设备,并且有这样的物品索引,然后该物品被“交换” - 被持有,现在我可以将这种持有的物品放入设备,库存或货物中。这就是为什么我需要在 Eq/Inv/Cargo 之间共享此类。
  • @mexikanoZ 听起来像 EquiptmentInventory 应该只有一个 List<Item> 和暴露的 AddRemove 方法。然后,当您交换它们时,您只需调用适当的方法。你甚至可能不需要继承关系。
【解决方案2】:

你有没有考虑过,不是“是一个”继承类型的关系,而是一个“包含一个”关系?

您可以按照以下方式进行操作:

public interface IHolded
{
     Bar Foo();
}

public class Holded: IHolded { ... }

现在你有两个选项来实现EquipmentInventory

  1. 通过只读属性直接暴露holded

     public class Inventory
     {
         public Inventory(IHolded holded) { ... }
         public IHolded Holded { get; }
     }
    
  2. 让他们实现IHolded 接口并委托 实现到holded

    public Equipment
    {
         private readonly IHolded holded;
    
         public Equipment(IHolded holded) { this.holded = holded; }
    
         public Bar Foo() { return holded.Foo() };
    }
    

这样您在创建EquipmentInventory 实例时注入Holded 对象,确保两个实例中的状态一致。

【讨论】:

    【解决方案3】:

    存储人员及其 HoldedId 的字典可能会起作用

    public class Holded
    {
        protected internal static Dictionary<string, int> _personHoldedIDs;
        internal string _person;
    
        public Holded(string person)
        {
            _person = person;
    
            if (_personHoldedIDs == null)
                _personHoldedIDs = new Dictionary<string, int>();
    
            if (!_personHoldedIDs.ContainsKey(_person))
                _personHoldedIDs.Add(_person, 0);
        }
    }
    
    public class Inventory : Holded
    {
        public Inventory(string person) : base(person) { }
    
        public void changeHoldedID()
        {
            _personHoldedIDs[_person] = 100;
        }
    }
    
    public class Equipment : Holded
    {
        public Equipment(string person) : base(person) { }
    
        public void writeHoldedID()
        {
            Console.WriteLine("Holded ID is: {0}!", _personHoldedIDs[_person]);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多