Рефакторинг для перемещения частного поля из одного класса в его вспомогательный класс?

EDIT. Я отправил запрос расширения Eclipse для этого рефакторинга.

Есть ли способ переместить частное поле из одного класса в его вспомогательный класс? Следующий UML-кукурузный царапины показывает, что я делаю вручную прямо сейчас. Класс C1 имеет приватную field и частную окончательную ссылку на объект Helper перед рефакторингом.

После рефакторинга все ссылки в C1' - field меняются на helper.getField() и helper.setfield(), если это необходимо.

UML Diagram

class Field {}

class C1 {
   final private Field field;
   final private Helper helper;

   public Field getField() {
      return field;
   }

   public C1() {
      helper = new Helper();
      field = new Field();
   }
}

class Helper {}

class C1Prime {
   final private HelperPrime helper;

   public Field getField() {
      return helper.getField();
   }

   public C1Prime() {
      helper = new HelperPrime();
   }
}

class HelperPrime {
   final private Field field;
   public HelperPrime() {
      field = new Field();
   }
   public Field getField() {
      return field;
   }
}

Я использовал возможности рефакторинга Eclipse совсем немного, но я не могу найти способ автоматизировать это.

Например, в идеале я бы перетащил private field/attribute/member из одного класса в другой и надеюсь, что Eclipse спросит меня, как я хочу обрабатывать неразрешенные ссылки. Он не предлагает предложений и не разбивает все ссылки.

Операция, которую я повторяю, заключается в разделении знаний и поведения, которые на самом деле не относятся к текущему классу. Я перемещаю атрибуты и поведение, которые ссылаются на определенные поля из исходного класса в новый класс "помощник".

Первым шагом в моем рефакторинге является перемещение полей. Ссылка на класс-помощник существует как поле в классе, с которого я рефакторинг. Чтобы не разорвать C1 во время рефакторинга, я думаю, было бы неплохо, если бы Eclipse предложила генерировать геттеры и сеттеры в Helper' и обновить ссылки в C1, чтобы использовать геттеры/сеттеры в новом классе.

Ответ 1

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

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

Когда вы создаете свой класс, сделайте его либо внутренним классом существующего класса, либо вторым классом в том же файле.

Если вы сделаете это внутренним классом, вы можете сначала скопировать методы, и они могут ссылаться на член в другом классе. После того как вы перейдете все функциональные возможности, вы можете переместить переменную. В этот момент ни одна из ссылок на переменную не должна обновляться, так как вы обращаетесь к ней одинаково независимо от того, в каком классе она находилась.

Создание класса вторым классом в том же файле может быть приятным, если вы также разделяете функциональность - он позволяет вам получить доступ ко всему сразу, без мышки между окнами. Когда вы закончите, просто перетащите новый класс в свой собственный Java файл, пересчитайте импорт, переформатируйте его и сохраните.

Я почти всегда использую одну из этих методологий при создании нового класса, который взаимодействует с существующими классами.

Ответ 2

Хорошо, для этого просто не имеет смысла работать в целом. Семантически это странная операция. Если вы переместите поле в новый, непересекающийся класс (скажем, от String до Integer), код, на который он ссылается, не будет иметь экземпляр нового класса, который будет использоваться для получения поля экземпляра.

Таким образом, существуют только особые случаи, когда это имеет смысл: когда поле является статическим членом или вы перемещаете его в родительский класс.

Для статических членов он отлично подходит для щелчка правой кнопкой мыши по полю, которое вы хотите переместить (имя переменной), и нажмите "Refactor- > Move". Выберите новый тип. Ссылки будут автоматически обновляться (попробуйте сами и посмотрите)

Если вы перемещаете его в/из родительского класса, вы можете использовать Refactor- > Pull Up или Push Down, но это не будет автоматически изменять ссылки для вас (только проблема с Push Down, с полиморфизмом Pull Up диктует, что ссылки все еще прекрасны).

Ответ 3

Не будет right click the field > Refactoring > Move делать?

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

Ответ 4

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

Ответ 5

Для функции Java вы можете просто щелкнуть правой кнопкой мыши по ее имени, а затем выбрать Refactor > Move. В мастере выберите новый класс, который теперь будет управлять этим методом.

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

Ответ 6

Если целевой класс еще не существует, вы можете использовать Refactor > Extract Class. Это создаст новый класс, содержащий выбранные вами поля, и добавьте поле этого типа в исходный класс.

Я не уверен, что вы можете сделать это для класса, который существует, но вы всегда можете использовать Extract Class, а затем cut'n'paste его содержимое в новый класс.