【问题标题】:C# abstract class static field inheritanceC#抽象类静态字段继承
【发布时间】:2011-04-02 07:31:20
【问题描述】:

我觉得我跳过了一两节 C# 课程,但这是我的困境:

我有一个抽象类,从中派生出多个子类。

我确信对于每个子类,我都会有一个构造函数,它需要某个静态对象作为模型,并且这个对象对于每个子类都是不同的。

我的第一个方法是在抽象父类中创建一个公共静态对象,然后,在我开始创建子类的任何实例之前,我会为每个子类修改它,但事实证明,这种方式我实际上只为抽象类创建一个静态对象,它的每个子类都使用它。

我该如何解决这个问题?

更准确地说,这里是伪代码:

父抽象类:

 abstract class AbstractClass
{
   static public ModelObject Model;
   ...
}

其中一个子类:

class Child : AbstractClass
{
    ...
    public Child()
    {
        this.someField = Model.someField;
    }
}

编辑:

模型需要是“ModelObject”类的成员,它不应该是单例或其他任何东西。

EDIT2:

更准确地说,我为国际象棋游戏选择了这个实现:我有一个用于棋子的抽象类,子类代表游戏的具体部分:棋子、骑士等。

抽象类继承自 MeshMatObject,该类表示具有基本功能的通用 3d 对象,如旋转、网格、材质、纹理等,它定义了国际象棋棋子的抽象方法,如 GetPossibleMoves()。

我上面谈到的模型对象是 MeshMatObject 的成员,在我看来,应该在类外定义一次,然后用于所有部分。我的意思是:例如,所有的 pawn 都具有相同的网格和纹理,所以我不认为每次制作 pawn 时都将模型作为参数。

【问题讨论】:

  • AbstractClass需要通过什么方式访问Model?
  • 您应该考虑将模型实例传递给子类的构造函数,而不是使用这样的静态字段。
  • 我同意 Trillian 的观点。有了静态模型,实在是违背了这里的封装精神。
  • @dtb:抽象类实际上并不需要访问模型。子类需要在其构造函数中访问它@Trillian:是的,这将是一个解决方案,实际上这是我的第一个实现,但是由于该类的所有对象都是在相同的确切模型之后构建的,我认为它应该更好在类中只定义一次模型并使用静态字段构造新实例。
  • 为什么它需要是静态的?您是否在所有类之间共享状态?

标签: c# inheritance static field abstract


【解决方案1】:

您可以通过将抽象类设为通用来绕过共享静态字段。每个泛型类都将获得它自己的静态字段副本。

abstract class AbstractClass<T>
{
   static public ModelObject Model;
   ...
}

然后每个子类将使用静态字段的不同实例。

class Child : AbstractClass<Child>
{
    ...
    public Child()
    {
        this.someField = Model.someField;
    }
}

AbstractClass 不引用泛型参数并不重要。您只是使用它为每个子类提供一个唯一的基类实例。

【讨论】:

  • 感谢您的输入,已经完成了一半。另一半来自 Justin R。如果我只使用您的解决方案,我将无法仅使用 AbstractClass 对象进行操作。例如,我很难布置一个 2D 抽象棋子数组。不管怎样,很高兴知道对于泛型类,每个孩子都会收到一份静态字段的副本。
【解决方案2】:

我倾向于使用类似于@shf301 的解决方案。根据您的需要,将基类设置为:

abstract class AbstractClass
{
}

abstract class AbstractClass<TModel> : AbstractClass
    where TModel : ModelObject 
{
   static public TModel Model;
   ...
}

这为我提供了一个可以在非泛型函数中使用的通用基类。这也允许派生类型选择确切的模型类型,并且可以减少强制转换。

【讨论】:

  • 完美运行!只是“...”在“AbstractClass”上。一个不错的简单实现,谢谢。还有一件事:这个实现是否有任何性能损失等?我看不出有什么理由,尤其是 VS 的“优化代码”功能,但只是确保。
  • 编辑:在我的例子中,类型约束应该是 AbstractClass;然后子类将被声明为 shf301 指出。这是因为我只需要为 AbstractClass 的孩子实现。类似于: AbstractClass : AbstractClass where T : AbstractClass and the child: ChildClass : AbstractClass
【解决方案3】:

工厂如何将您的类与继承的模型解耦:

public static class ModelObjectFactory
{
    public static ModelObject GetModel<T>(T obj)
    {
        // return ModelObject according to type of parameter
    }
}

class Child
{
    public Child()
    {
        ModelObject mo = ModelObjectFactory(this);
        this.someField = mo.someField;
    }
}

【讨论】:

  • 在其他情况下,工厂会工作得更好。在这个特殊的情况下,我认为我会使情况过于复杂(如果这是一个词);但谢谢你的想法!
  • 拥有单一职责的对象永远不会使事情复杂化。检查 SOLID 原则。如果可能的话-1评论:)
猜你喜欢
  • 2015-04-07
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多