Создать экземпляр класса, который используется в конструкторе его внешнего класса
Я пытаюсь создать экземпляр класса, который используется в конструкторе его внешнего класса. Ссылаясь на код ниже, мне нужно 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
это было создано с.
Так что либо:
- Сделать
TimeOnlineInfo
создание работы дляUserData
, - Избавляться от
TimeOnlineInfo
, (Невозможно, если ваш класс уже большой, но с другой стороны, если ваш класс такой большой, вам, вероятно, нужно заняться и другими вещами.) Сделайте ваш внутренний класс статичным и управляйте соединением явно:
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(); }
}
Далеко от идеала, но это решило бы и пару других проблем.