【问题标题】:Use of abstract classes, interface and List in C#C#中抽象类、接口和List的使用
【发布时间】:2013-04-29 19:20:54
【问题描述】:

我有以下代码部分,我正在尝试实现一个返回列表的方法。我的结构如下:抽象类“坐标”->公共类“YCoordinate”,我的接口指向“YCoordinate”。我不希望我的界面直接与我的抽象类聊天,因为我觉得我的抽象类的实现负责工作。

界面:

interface IYCoordinate
{
    System.Collections.Generic.List<Coordinates> GetYCoordinateList();
}

抽象类:

public abstract class Coordinates
{
    private int coordinatePriority;
    private int coordinate;

    public Coordinates(int CoordinatePriority, int Coordinate)
    {
        this.CoordinatePriority = CoordinatePriority;
        this.Coordinate = Coordinate;
    }

    public Coordinates() { }
    public int CoordinatePriority { get { return coordinatePriority; } set { coordinatePriority = value; } }
    public int Coordinate { get { return coordinate; } set { coordinate = value; } }

    public virtual List<Coordinates> GetYCoordinateList()
    {
        throw new System.NotImplementedException();
    }
}

接口和抽象类的实现(这是中断的部分):

public class YCoordinate : Coordinates, IYCoordinate
{
    public override List<Coordinates> GetYCoordinateList() 
    {
        List<Coordinates> _list = new List<Coordinates>();
        _list.Add(new IYCoordinate(1, 5000));
        _list.Add(new IYCoordinate(2, 100000));
        return _list;
    }
}

但是,我试图返回坐标列表并卡在“YCoordinate”类中的公共覆盖函数上,因为我无法直接实例化坐标类(因为它是抽象的)。如何返回坐标列表?如果我如上所示输入 IYCoordinate,也会发生同样的错误。

也许我的实现完全错误?任何做得更好的建议都将受到欢迎。

稍后会有 XCoordinate 类等等。如果这种方法看起来有点过分,那是因为我试图掌握这背后的理论。

【问题讨论】:

  • IYCoordinate.GetYCoordinateList() 应该返回 IList&lt;Coordinates&gt;,而不是 List&lt;Coordinates&gt;
  • @cdhowie 编译器不要求将接口作为接口中定义的方法的返回结果返回。出于设计和体系结构的原因,您可以选择这样做,但是,由 OP 编写的接口定义不是这里的问题。 IMO YCoordinate 类的缺陷在于它拥有自己的列表。这将更好地由另一个班级拥有。 OP 的示例有点令人困惑。
  • @CodeMonkeyKing 我从来没有说过编译器会抱怨。我的评论旨在灌输良好的设计实践,而不是指出错误。
  • @cdhowie 这似乎是一条诫命,而不是设计“最佳实践”。这不是必需品。贴出的代码问题远比改成IList接口更深。
  • @CodeMonkeyKing 这些问题实际上是无关的,这就是为什么我发表评论而不是答案。

标签: c# interface abstract


【解决方案1】:

我会这样做:

1) 你有一个接口 - IYCoordinate,但你说你也想拥有IXCoordinateIZCoordinate。只需使用单一界面 - ICoordinate 和一个功能 - GetCoordinateList

interface ICoordinate
{
    IList<Coordinates> GetCoordinateList();
}

其实,如果你使用我的方法,这个接口是可以消除的

2) 在您的抽象类中,您将有一个 GetCoordinateList 的存根,它什么都不做

public abstract class Coordinates: ICoordinate
{
    public virtual List<Coordinates> GetCoordinateList()
    {
        throw new System.NotImplementedException();
    }
}

其实你可以完全去掉ICoordinate接口,只使用抽象类。没关系。

3) 您将从 Coordinates 类派生一个(或多个)类,并根据需要实现 GetCoordinate

public class YCoordinate : Coordinates
{
    public override List<Coordinates> GetCoordinateList() 
    {
        List<Coordinates> _list = new List<Coordinates>();
        _list.Add(new YCoordinate(1, 5000));
        _list.Add(new YCoordinate(2, 100000));
        return _list;
    }
}

因此,您只有一个接口和一个函数名来从派生自Coordinates 的任何类中获取坐标。如果您以后要添加XCoordinate 类,您将需要实现具有相同名称的相同功能。 当您将实例化 XCoordinateYCoordinateWhateverCoordinate 类时,您将始终知道您需要一个 GetCoordinateList 函数

var coordClass = new XCoordinate();
coordClass.GetCoordinateList();

此外,当传递必须有GetCoordinateList 成员的东西时,您可以在任何地方使用您的接口ICoordinate 或抽象类坐标。

【讨论】:

  • 在你说IList的界面中,我只是改变了那个列表,因为它在抱怨它。以为我可以保留 IList 并更改抽象类中的函数等等。但是我仍然对步骤 nr 3 感到困惑。你说 new List 但然后在下一行谈论 YCoordinates?如果我将它保留为 YCoordinates,它会抱怨这两个参数没有构造函数。我无法将其更改为坐标,因为它是抽象的。
  • 我将所有构造函数从抽象类移到 YCoordinate,现在它可以工作了。但是,我希望不要键入该类的每个实现,但是我现在按照以前的建议进行了具体的类。
  • @Sonja,您可以在抽象类(坐标)中有一个构造函数,并且您必须从派生类(YCoordinate)中的构造函数中调用它。我会将其发布在答案中,因为它更具可读性。
  • 好吧,如果您需要将这 2 个参数传递给基构造函数(坐标类),我们在这里无能为力 - 这就是 C# 语言的设计方式,基类没有其他选择如果你不通过它们,就知道这些参数。如果你不需要这 2 个参数,你可以不带任何参数调用基类的构造函数。
【解决方案2】:

在这些方面:

_list.Add(new IYCoordinate(1, 5000));
_list.Add(new IYCoordinate(2, 100000));

您需要实例化派生自Coordinates 类的类的对象。在这里,您试图创建一个接口的新实例,但您不能这样做——接口成员没有定义!

创建Coordinates 的子类并实例化它。 (或者从这个类的定义中删除 abstract 关键字——不清楚为什么它是抽象的,因为没有抽象成员。)

【讨论】:

  • Tx... 我错过了将抽象类中的方法更改为 public abstract List GetYCoordinateList();现在将尝试查看您的其他建议。
  • 您似乎想要创建YCoordinate 的实例,因此请尝试使用new YCoordinate 而不是new YICoordinate
【解决方案3】:

你至少需要一个具体的类。

目前你只有抽象类和接口。

【讨论】:

  • 我明白了,忙着看下面cdhowie的推荐
【解决方案4】:

简单的答案....更改这两行:

    _list.Add(new IYCoordinate(1, 5000));
    _list.Add(new IYCoordinate(2, 100000));

到这里:

    _list.Add(new YCoordinate(1, 5000));
    _list.Add(new YCoordinate(2, 100000));

请注意,我在那里创建类,而不是界面。

长答案...Blablablaster 说对了 :-)

【讨论】:

    【解决方案5】:
    • 从 Blabblablaster 答案开始 - 在我看来,这里不需要接口。

      公共抽象类坐标 { 公共 int CoordinatePriority { 获取;放; } 公共 int 坐标 { 获取;放; }

      protected Coordinates(int CoordinatePriority, int Coordinate)
      {
          this.CoordinatePriority = CoordinatePriority;
          this.Coordinate = Coordinate;
      }
      
      public abstract List<Coordinates> GetCoordinateList();
      

      }

    正如您所注意到的,我创建了一个抽象方法,而不是接口中的方法。 每个派生类都必须实现这个方法。

    class YCoordinate:Coordinates
    {
        public YCoordinate(int CoordinatePriority, int Coordinate) : 
            base(CoordinatePriority, Coordinate) //Call constructor of baseclass
        {
        }
    
        public override List<Coordinates> GetCoordinateList()
        {
            List<Coordinates> list = new List<Coordinates>();
            list.Add(new YCoordinate(1, 5000));
            list.Add(new YCoordinate(2, 100000));
            return list;
        }
    }
    

    【讨论】:

    • 谢谢你,我现在要玩这个。使用接口的原因是因为我正在学习如何正确实现接口和抽象,但我理解并不总是需要同时使用它们或完全取决于场景。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 2011-01-19
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    相关资源
    最近更新 更多