Рефакторинг для перемещения частного поля из одного класса в его вспомогательный класс? - PullRequest
10 голосов
/ 05 октября 2010

РЕДАКТИРОВАТЬ : я отправил запрос на улучшение 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, но не могу придумать, как это автоматизировать.

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

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

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

Ответы [ 6 ]

8 голосов
/ 05 октября 2010

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

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

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

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

2 голосов
/ 05 октября 2010

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

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

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

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

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

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

1 голос
/ 05 октября 2010

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

1 голос
/ 05 октября 2010

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

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

0 голосов
/ 05 октября 2010

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

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

0 голосов
/ 05 октября 2010

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

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

...