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

Я пытаюсь создать экземпляр класса, который используется в конструкторе его внешнего класса. Ссылаясь на код ниже, мне нужно UserData объект, но мне также нужен TimeOnlineInfo объект, чтобы создать его, и я не вижу способа получить TimeOnlineInfo объект без первого экземпляра UserData так как TimeOnlineInfo не является статичным Я не могу сделать его статичным, потому что ему нужен доступ к методу из его внешнего класса. Можно ли как-нибудь заставить это работать или получить наиболее похожий эффект? Я понял, что могу просто сделать классы статичными и не сохранять данные непосредственно в методе addTime, но я уже был на полпути к этому вопросу, и мне любопытно посмотреть, есть ли способ сделать это.

Вот очень упрощенная версия моего кода:

class UserData {
    TimeOnlineInfo timeOnline;

    public UserData(Object data1, Object data2, Object data3, Object data4, Object data5, TimeOnlineInfo timeOnlineInfo){
        this.timeOnlineInfo = timeOnlineInfo;
    }

    public class TimeOnlineInfo {
        private int time;

        public TimeOnlineInfo(int time){
           this.time = time;
        }

        public void addTime(int time){
            this.time += time;
            UserData.this.saveData();
        }
    }
}


UserData userData = new UserData(new UserData.TimeOnlineInfo());//Doesn't work because PlayInfo is not a static class
UserData userData = new UserData(userData.new TimeOnlineInfo());//This is just a stupid because i'm using the uncreated object in its own constructor

3 ответа

Решение

У вас есть общее замешательство по поводу нескольких вещей. Давайте начнем с самого начала.

Во-первых, это не конструктор.

public void UserData(TimeOnlineInfo timeOnlineInfo){
    this.timeOnlineInfo = timeOnlineInfo;
}

Вы хотели бросить void декларация.

public UserData(TimeOnlineInfo timeOnlineInfo){
    this.timeOnlineInfo = timeOnlineInfo;
}

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

Например, вам придется использовать new UserData().new TimeOnlineInfo(int) например TimeOnlineInfo, но это только:

  • если вы решили создать конструктор без аргументов для UserData
  • если вы действительно не заботитесь о случае UserData ты возвращался

Если вы действительно хотите сохранить этот дизайн, рассмотрите возможность передачи int вашему строителю, чтобы он мог быть передан в экземпляр TimeOnlineInfo,

class UserData {
    TimeOnlineInfo timeOnlineInfo;

    public void saveData() {
        // stub
    }

    public UserData(int value) {
        this.timeOnlineInfo = new TimeOnlineInfo(value);
    }


    public class TimeOnlineInfo {
        private int time;

        public TimeOnlineInfo(int time){
            this.time = time;
        }

        public void addTime(int time){
            this.time += time;
            UserData.this.saveData();
        }
    }
}

Прежде всего, ваш UserData Конструктор не один.

Вы объявили это как void метод, так что нет UserData конструктор будет компилироваться с параметризацией TimeOnlineInfo пример.

Но это может быть только опечатка.

Затем, если вы можете реализовать конструктор без параметров для UserData поверх существующего вы можете использовать следующую идиому:

UserData ud = new UserData(new UserData().new TimeOnlineInfo(42));

Однако, это, кажется, указывает на более общую проблему в вашем дизайне, так как вы в основном должны инициализировать UserData дважды, чтобы получить полезный экземпляр.

Идея здесь в том, что вы либо вводите TimeOnlineInfo в конструкторе, в этом случае TimeOnlineInfo вероятно, будет использоваться более широкими областями, чем просто UserDataили вы используете только TimeOnlineInfo в UserData, в этом случае используйте пустой конструктор для UserData и инициализировать ваш внутренний TimeOnlineInfo внутри.

Вы можете изменить свой конструктор на это:

public void UserData(int time){
    this.timeOnlineInfo = new TimeOnlineInfo(time);
}

Вы также можете сделать TimeOnlineInfoконструктор частный, чтобы остановить инстанцирование мошенника TimeOnlineInfo экземпляров.

Но, основываясь на размещенном вами фрагменте, я, вероятно, избавлюсь от TimeOnlineInfo полностью.


Меня предупредили, что то, что я считал конструктором, не одно. Итак, обо всем по порядку, никогда не создавайте обычные методы с тем же именем, что и у класса.

Остальное все еще остается, проблема с этим соглашением состоит в том, что каждый может создать TimeOnlineInfo объект, который сработает UserData.this.saveData() даже если на него не ссылается UserData это было создано с.

Так что либо:

  1. Сделать TimeOnlineInfo создание работы для UserData,
  2. Избавляться от TimeOnlineInfo, (Невозможно, если ваш класс уже большой, но с другой стороны, если ваш класс такой большой, вам, вероятно, нужно заняться и другими вещами.)
  3. Сделайте ваш внутренний класс статичным и управляйте соединением явно:

    public void setTimeOnlineInfo(TimeOnlineInfo timeOnlineInfo){
    if (timeOnlineInfo.userData != null) {
        throw new IllegalArgumentException( "TOI already belongs to other UserData" );
    }
     if (this.timeOnlineInfo != null) {
         this.timeOnlineInfo.userData = null;
     }
     timeOnlineInfo.userData = this;
     this.timeOnlineInfo = timeOnlineInfo;
    

    }

    открытый статический класс TimeOnlineInfo { private int time; личные данные пользователя userData;

     public TimeOnlineInfo(int time){
        this.time = time;
     }
    
     public void addTime(int time){
         this.time += time;
         userData.saveData();
     }
    

    }

Далеко от идеала, но это решило бы и пару других проблем.

Другие вопросы по тегам