0

Я пытаюсь создать экземпляр класса, который используется в конструкторе его внешнего класса. Ссылаясь на приведенный ниже код, мне нужен объект 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 
+1

курица и яйцо –

+0

я не думаю, что это особенно хорошее расположение, если '' TimeOnlineInfo' и UserData' находятся в строгом соотношении 1 к 1 (так как они кажутся), почему у вас есть отдельный, общедоступный класс «TimeOnlineInfo»? Конечно, могут быть причины для этого, но из того, что вы опубликовали, самым простым решением было бы избавиться от 'TimeOnlineInfo' вообще. – biziclop

ответ

2

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

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

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(); 
     } 
    } 
} 
+0

Я бы все-таки сделал 'TimeOnlineInfo' частным :) – biziclop

+0

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

+0

@kmecpp. Это не ваша вина, эти проблемы трудно упростить для публикации без упрощения. – biziclop

0

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

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; private UserData userData;

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

    }

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

+0

То есть *** не *** конструктор. – Makoto

+0

@Makoto Вы правы ... pff, Это другое дело, чтобы исправить. – biziclop

+0

Это также не самая лучшая идея, потому что UserData уже имеет полный набор всех параметров, необходимых для хранения всех разных данных. Кроме того, TimeOnlineInfo является более сложным по типу, чем я сделал, кажется, он не просто принимает один параметр. – kmecpp

1

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

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

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

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

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

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

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

+0

Да, сожалею об этом, это была опечатка. Конструктор без параметров не похож на хорошую идею из-за вашей причины, но я также не хочу, чтобы у вас возникла необходимость создать пустой, бесполезный объект, кроме его единственной цели - создать вложенный класс. – kmecpp

+0

@kmecpp Да, это похоже на уродливое обходное решение. Вот почему я настаиваю на последнем абзаце о части дизайна. – Mena

+1

@kmecpp - это не просто бесполезно; он будет ссылаться на неправильный внешний объект. – ZhongYu