C#:帮助设计嵌套类的结构

本文关键字:结构 嵌套 帮助 | 更新日期: 2023-09-27 17:56:54

我需要一个描述行星系统的类系统。

我的第一堂课是原子空间体:

public class SpaceBody
{
    public string Name;
    public float Mass;
   // and so on
}

第二个是空间体系统,它也是SpaceBody:

public class SpaceBodySystem<ChildType>: SpaceBody where ChildType: SpaceBody, new()
{
    // ...
    public List<ChildType> Children;
    // ...
}

接下来,我有一颗星:

public class Star: SpaceBodySystem<SpaceBody>
{
    public float Intencity;
    // ...
}

最后,整个恒星系统是这样的(它可以有多个星):

public class StarSystem: SpaceBodySystem<Star>
{
    public bool OccupiedByAliens;
    // ...
}

问题是:恒星应该有行星(SpaceBodySystem),而行星反过来可能有自己的卫星,这些卫星也可能有自己的卫星等等。嵌套深度是无限的。

以我目前的班级制度,这是不可能的。我必须写这样的东西,但这个丑陋的解决方案的层次结构级别有限。

public class StarSystem: SpaceBodySystem<SpaceBodySystem<SpaceBodySystem<SpaceBody>>>
{
    public float Intencity;
    // ...
}

我要求社区给我一些建议,如何改进这种结构。我想过其他方案(接口、组合+委托),但没有设法得到一个可接受的解决方案。

非常感谢任何帮助。

C#:帮助设计嵌套类的结构

如果你需要一个系统中有多个太阳的可能性,也许你也希望两个行星共享一个卫星的可能性。

在这种情况下,也许你应该有一个子系统,它有一个主体数组和一个卫星数组。在太阳系中,您可以使用恒星作为主体,行星作为卫星。在一个星系中,也许你可以定义一些抽象的中心点/航点作为主体,所有的太阳系都是卫星。

因此,对于我们的太阳系,

你有子系统"太阳系",主体是太阳和卫星行星,每个行星也是子系统。子系统地球有一个主体地球和一个卫星月球。

拥有一个带有一个主体地球的子系统地球可能听起来有点多余,但也许你可以通过使用接口来解决这个问题,所以像这样的简单子系统(有一个主体)可以由一个同时实现ISubSystem和IMainBody的类来实现。

或者你可以使实现更容易,使地球(系统)

成为一个单独的子系统,有一个主体的数组,即地球(行星)和一个带有一个卫星的阵列,即子系统月球(系统),包含主体月球,没有卫星。

我认为一个类可以建立一个行星系统:

public class SpaceBody
{
    public string Name;
    public float Mass;
    public float Distance;
    public bool clockwise;
    //...
    public SpaceBody RevolvesAround;
    List<SpaceBody> Satellites;
}

如果您的系统基类可以具有本身是同一基类的实例或派生自同一基类的子类,那么您不需要像那样嵌套。我举个例子:

public class SpaceBodySystem<ChildType>: SpaceBody where ChildType: SpaceBody, new()
{
    public List<ChildType> Children;
}

因此,SpaceBodySystem具有SpaceBody类型的子项,它本身就是一个SpaceBody

public class StarSystem : SpaceBodySystem<Star>
{
}

这个类可以表示一颗星星,或者两颗星星的二进制对,或者其他什么。

public class PlanetarySystem : SpaceBodySystem<Moon>
{
    public Planet CentralPlanet;
}

这可以代表具有任意数量卫星的行星,其中Planet继承自SpaceBody

public class SolarSystem : SpaceBodySystem<PlanetarySystem>
{
    public StarSystem CoreStar;
}

这个类现在可以代表一个太阳系,有一些恒星的配置,以及所有可能有卫星的行星的孩子。

简而言之,你不需要继续嵌套SpaceBodySystem<SpaceBodySystem<SpaceBodySystem<SpaceBody>>>,因为SpaceBodySystem继承自SpaceBody,所以如果你只有SpaceBodySystem<SpaceBody>,那么这个内SpaceBody可能是一个SpaceBodySystem,它可能有更多的子项,但不需要知道。这就是多态性的美妙之处。

另外,我想从数据文件加载我的系统。假设我有这个输入数据(在附件中)。我有虚拟方法读取并创建SapceBody的对象。

class SpaceBody...
{
    ...
    public virtual void CreateGameObject()
    {
        instance = new GameObject();
    }
    ...
}
class SpaceBodySystem...
{
    ...
    public override void CreateGameObject()
    {
        base.GameObject();
        foreach(ChildType child in Children)
        {
            child.CreateGameObject();
        }
    }
    ...
}

class Star: SpaceBodySytem<SpaceBody>
{
    ...
    public override void CreateGameObject()
    {
        base.GameObject();
        doExtraWorkForTheStar();
    }
    ...
}
StarSystem.CreateObject();
 // for attached file, will load and create one star (Sun) and nine planets.

所以,如果我使用anaximander提出的声明,系统看不到孩子的孩子。例如,地球是SpaceBody(但应该是SpaceBodySytem),在这种情况下不会创建月球。

GolezTrol的想法很好。

Solarsystem.json