Объект класса внутри себя

#c# #oop #xna

#c# #ооп #xna

Вопрос:

эй, я думаю, мог бы я создать экземпляр класса с самим по себе…

Моя проблема в том, что я создаю 3D сферы для планет и их спутников, данные которых я храню в Object. Я передаю конструктору моего класса planet параметры для «Размера», «Радиуса орбиты», «Текстуры», «Скорости вращения» и так далее. Я должен создать другой класс для Moon of Planets, который является точной копией класса moon.

Я думал, смогу ли я создать объект класса внутри самого себя. Передайте параметр для списка массива объектов самого по себе для создания и, например, для земли я передам «1» для создания одной луны, и поскольку у луны будет тот же конструктор, я передам «0» для отсутствия лун луны. для создания.

Что-то вроде этого

 class Planet
{
    Model     u_sphere;
    Texture2D u_texture;
    //Other data members

    List<Planet> Moons = new List<Planet>(); 

    Planet()
    {
    //Default Constructor
    }

    //OverloadedCustom Constructor
    Planet(Model m, Texture2D t, int moon_count)
    {
       u_sphere  = m;
       u_texture = t;

       while(moon_count > 0)
       {
           Model     moon_sphere = LoadMesh("moon.x");
           Texture2D u_texture   = LoadTexture("moon.bmp"); 
           Planet    temp        = new Planet(moon_sphere,moon_texture,0);
           Moons.Add(temp);
           moon_count--;
       }
    }
    //Others Getters amp; Setters
}
  
  • Возможно ли это каким-то образом?

  • или каков наилучший практический подход к такого рода проблемам?

p.s Я использую C # и Microsoft X.N.A. Framework

Комментарии:

1. Почему бы не попробовать это? Это работает точно так, как вы написали. (Конечно, while цикл можно упростить.)

Ответ №1:

Да, почему бы и нет? Но вы можете захотеть создать базовый класс типа, CelestialBody от которого будут исходить как ваши Planet , так и Moon классы. И вам не обязательно передавать Planet ‘s Moon s в конструктор, но вы можете просто сделать так, чтобы Planet это выглядело следующим образом:

 public class Moon : CelestialBody
{
    //Moon-only properties here.
}

public class Planet : CelestialBody
{
    //Planet-only properties here.
    public List<Moon> Moons { get; set; }
}
  

А затем добавьте Moon такие:

 myPlanet.Moons.Add(new Moon(...));
  

Например. абстрагирование -удаление части информации, поскольку a Moon не является Planet .

Комментарии:

1. Подход Джоша выполняет то же самое, что я пытался сказать. Будут атрибуты, которые являются общими для обоих классов. Я не уверен, что стал бы использовать интерфейс — я бы пошел по пути базового класса CelestrialBody, от которого наследуются Planet и Satellite. Тогда планета имела бы свои собственные дополнительные свойства (Список<Спутник>, Афелий, перигелий), а спутник имел бы свои собственные свойства (перигей, апогей).

2. У меня это тоже изначально было как базовый класс — и, вероятно, именно так я бы его реализовал.

3. В любом случае, это упрощает ответ.

4. @Amitd — конечно, это может быть что-то, что вы добавите. Но если предположить, что модель данных больше, чем показано здесь, этот AddMoon помощник превращается в более чем 100 методов-оболочек, хотя на самом деле он ничем не отличается от myPlanet.Moons.Add(...) (ну, это один дополнительный символ).

Ответ №2:

Более объектно-ориентированным подходом могло бы быть выделение любого специфичного для moon кода в его собственный класс. Это может помочь сохранить ваш код более организованным по мере его увеличения. Я знаю, что луна на самом деле не планета, но кого это волнует?

Недостатком этого, однако, является то, что теперь вы ограничиваете свои варианты наследования, поэтому вам придется подумать о дизайнерском решении.

 class Planet 
{     
    Model     u_sphere;
    Texture2D u_texture;
    List<Planet> Moons = new List<Planet>();

    Planet(){}

    Planet(Model m, Texture2D t, int moon_count)     
    {
        u_sphere  = m;
        u_texture = t;

        while(moon_count > 0)        
        {
            Planet    temp        = new Moon();
            Moons.Add(temp);
            moon_count--;
        }     
    }
} 


class Moon : Planet
{   
    Moon()
    {
        u_sphere  = LoadMesh("moon.x");
        u_texture = LoadTexture("moon.bmp");
    }
}
  

Ответ №3:

Конечно. Вы просто повторно используете класс снова. Имейте в виду, что некоторые свойства класса могут больше не применяться (не существует такого понятия, как луны лун, не так ли?)

Возможно, вы захотите добавить конструктор, который передает логическое значение, isChild. Таким образом, вложенный дочерний элемент может знать, что он действительно дочерний элемент.

Комментарии:

1. Спутники на самом деле могут иметь спутники.

Ответ №4:

То, что у вас уже есть, кажется довольно точным. Одним из возможных улучшений было бы создать новый вызываемый класс Moon и наследовать от него Planet . Таким образом, вы могли бы добавить дополнительные свойства / функциональность для Moon , такие как сохранение ссылки на владельца Planet .

Ответ №5:

Конечно, это допустимый код.

Этот тип дизайна может быть сомнительным по другим причинам. Зачем классу Planet знать, как создавать другие экземпляры Planet и т.д. Гораздо понятнее, если логика, создающая planets, находится вне класса imo.

Ответ №6:

Хотя ваш код в порядке, на мой вкус, он просто выглядит слишком близким к бесконечному циклу. Если когда-либо вы меняли это 0 на 1, тогда БАЦ! Одним из способов сделать это более надежным было бы создать дополнительный конструктор и связать их в цепочку. Таким образом, рекурсии не происходит.

 Planet(Model m, Texture2D t, int moon_count) : this(m, t)
{
    while(moon_count > 0)
    {
        Model     moon_sphere = LoadMesh("moon.x");
        Texture2D u_texture   = LoadTexture("moon.bmp");
        Planet    temp        = new Planet(moon_sphere, moon_texture);
        Moons.Add(temp);
        moon_count--;
    }
}

Planet(Model m, Texture2D t)
{
    u_sphere  = m;
    u_texture = t;
}