【问题标题】:Better Way To Put Two Different Classes w/ Same Base Class In Same List?将具有/相同基类的两个不同类放在同一个列表中的更好方法?
【发布时间】:2011-07-26 15:34:15
【问题描述】:

假设我有一个名为 BaseClass 的基类:

public BaseClase{
    public bool isCool;
}

现在假设我有两个继承自 BaseClass 的类

public Class1: BaseClass{
    public bool isGreen;
}

public Class2: BaseClass{
    public bool isPurple;
}

现在假设我想通过创建一个列表来创建一个包含 Class1 和 Class2 实例的列表;

var genericList = new List<BaseClass>();

接下来,让我们将 Class1 和 Class2 的实例添加到 genericList。

genericList.Add(new Class1());
genericList.Add(new Class2());

现在,我有一个问题。如果我想访问 Class1.IsGreen 或 Class2.IsPurple,我必须将 genericList 中的每个项目转换为 Class1 或 Class2。

foreach(var item in genericList){
    if(item is Class1){
        var temp = (Class1) item;
        temp.IsGreen = true;
    }
    if(item is Class2){
        var temp = (Class2) item;
        item.IsPurple = true;
    }
}

这就是你应该做的事情吗?这对我来说似乎很笨拙,而且我正在编写的使用这种类型的代码结构的代码的复杂性已经失控了。我是继承的新手,想知道这是否只是你应该做的事情,或者是否有更好的选择。

【问题讨论】:

  • 除非您想解决如何迭代这个类层次结构的确切示例,否则您必须更具体地了解您的特定域才能告诉您是否你做出了最好的选择。
  • 看起来您可能想要一个在每个类中具有不同实现的方法(多态性)。然后,您可以为列表中的每个项目调用相同的方法。

标签: c# inheritance


【解决方案1】:

这真的取决于你想要做什么。如果您可以抽象出该属性,例如IsSelected,那么您可以在您的BaseClass 上将其作为虚拟或抽象属性公开。这样你就不必在你的 for 循环中转换你的项目了。

或者您可以将其抽象为抽象/虚拟方法,例如UpdateColor(bool)。然后每个派生类都可以覆盖它并为自己设置适当的属性。

还有其他几种替代方法,包括接口和扩展方法,您可以使用它们来使其更简洁。

【讨论】:

    【解决方案2】:

    基本上没有更好的选择,虽然如果你只想操作,比如Class1,那么你可以使用OfType扩展

    var genericList = new List<BaseClass>();
    genericList.Add(new Class1());
    genericList.Add(new Class2());
    
    foreach(var item in genericList.OfType<Class1>())
    {
      // no need to cast
      item.IsGreen = true;
    }
    

    【讨论】:

    • 这样好很多,实现起来也不难
    【解决方案3】:

    如果你能以某种方式抽象出你在循环中正在做什么,例如,你正在为一个项目应用默认颜色,那么公开方法 IEntity.SetDefaultColors(IColorInformation) 并在每个项目类中实现它。

    顺便说一句:考虑Interface segregation principle 并为您的实体引入一个通用接口,例如IEntity

    【讨论】:

      【解决方案4】:

      为了更好(或更糟)说明,我将把 IsGreen 更改为 IsSpecial,将 IsPurple 更改为 MaximumHappiness——这样我们就可以清楚这两个属性代表两个非常不同的东西。

      处理它的一种方法是使它们成为基类的两个属性(如果适用),因此您不必对它们进行类型转换。

      另一种方法是为基类提供一个函数(继承类可以覆盖该函数)。例如,该函数可以称为“DoSpecialThing”,在其中您可以访问子类的任何属性。

      如果保证属性是布尔值(并代表一些相关的想法),那么您也许可以使用标志。例如:

      [Flags]
      enum MoodType
      {
          //Moods
          Happy,
          Sad,
          Elated,
          Overjoyed,
          Depressed,
      
          //Mental States
          Confused,
          Alert,
          Sluggish,
      
          //Other
          Sleepy,
          Awake
      }
      

      所以现在基类可以有一个名为“State”的属性或其他东西,它可以是上述标志的任意组合。因此,您可以在一个属性中指示一个对象是 Sleepy、Confused 和 Happy。

      您可以阅读有关标志的更多信息(并确定它们是否适用于您的情况)at this link

      我也推荐this SO question。特别是投票最多(尽管未被接受)的答案。

      【讨论】:

        【解决方案5】:

        我会这样说,伪代码!

        public abstract BaseClase{
            public bool isCool;
            public abstract setColor();
        }
        
        public Class1: BaseClass{
            public bool isGreen;
        
            public override void SetColor() {IsGreen=true;}
        }
        
        public Class2: BaseClass{
            public bool isPurple;
            public override void SetColor() {IsPurple =true;}
        }
        
        foreach(var item in genericList){
            item.SetColor();
        }
        

        应该工作..

        问候。

        【讨论】:

          猜你喜欢
          • 2013-01-21
          • 2023-03-27
          • 1970-01-01
          • 2020-03-20
          • 2018-12-21
          • 1970-01-01
          • 1970-01-01
          • 2017-11-05
          • 1970-01-01
          相关资源
          最近更新 更多