【问题标题】:Using an interface as a field type but have the base class pick the derived struct使用接口作为字段类型,但让基类选择派生结构
【发布时间】:2014-03-02 01:20:00
【问题描述】:

标题可能有点难以描述,但我会在这里尽可能清楚地解释情况。我创建了一个类,该类将被其他人创建的类继承。我的类包含一个使用我创建的 IShape 接口的形状结构变量,如下所示:

IShape Bounds = new Rectangle(/*arguments go here*/);

如何让最终用户控制要使用的形状,同时仍然允许他访问所选形状的方法和字段(无需 24/7 开箱)?基本上我希望用户选择他想要的形状,但仍然有 IShape 形式的形状来执行诸如碰撞之类的东西。例如:

Bounds = new Triangle(/*arguments*/);
Bounds.Point3 = new Point(20f, 20f); //this property would be from the Triangle : IShape struct only and is not inherited from IShape

有没有办法或解决方法让最终用户轻松完成这项工作?

【问题讨论】:

  • 你可以尝试使用泛型。

标签: c# interface usability


【解决方案1】:

一种可能的解决方案是使用具有接口约束的泛型类。所以声明看起来像:

public class MyClass<TShape> where TShape : IShape
{
    protected TShape Bounds;
    //Rest of class
}

或者,您可以通过通用方法提供对形状的访问,该方法将集中在哪里进行铸造:

public class MyClass
{
    private IShape Bounds;

    protected TShape GetBounds<TShape>() where TShape : IShape
    {
        return (TShape)Bounds; //Note this will throw an exception if the wrong shape is specified
    }
    //Rest of class
}

如果基类应该负责了解自己的形状类型,则前者更合适。如果基类不知道其形状类型,而继承类(或调用类,如果您将其公开)应该知道,则后者更合适。

但是,虽然其中一种解决方案可能非常适合您的情况,但必须这样做有点代码味道。如果您的类大部分时间都必须知道和跟踪特定的具体类,那么使用接口没有多大意义。最好的解决方案可能是更改您的设计,尽管如果不了解您拥有的更多内容,很难就此提供建议。

【讨论】:

  • 感谢您的反馈。如果我必须选择,我会选择第二个选项。我之所以选择这个设计,是因为我实现了一个可以采用任何形状的碰撞系统(因此是 IShape 界面)。 github.com/Villermen/HatlessEngine/blob/master/… 是对象的位置,BoundBox 在这里仍然是一个矩形。我想将其更改为 IShape 或类似系统。既然您将其视为 borky 代码,您有什么不同的建议吗?
  • @Villermen 好吧,我不太确定为什么您有此要求,以便能够随时按确切类型获得形状。您是否考虑并拒绝了所有这些可能性: - 边界形状是不可变的 - 只允许用新的边界形状替换边界形状,而不是修改现有的 - 无论外部代码首先设置形状,都保持精确的引用只要需要就输入 - 根本没有形状子类型,让 Shape 获取任意长度的点列表 (> 2)
  • 在考虑了用户实际上会用它做什么之后,我选择了您的第一个选项。用户可以设置一个绑定的形状,然后他唯一无法访问的可能是旋转,但我甚至可以为此制定一个解决方法。所以用户需要做的就是为其分配一个新的形状。如果他想改变,例如形状的宽度或旋转,如果它是一个矩形,他只需要铸造它。感谢您的帮助本!
猜你喜欢
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-12
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 2013-08-16
相关资源
最近更新 更多