Как заменить аналогичный код из разных полей внутри разных классов в Java?

#java #oop #for-loop

#java #ооп #for-цикл

Вопрос:

Я работаю над проектом Java, который имеет несколько классов, которые имеют переменную экземпляра объектов из других классов. Например, объект BigClassA содержит массив объектов SmallClassA; объект BigClassB содержит массив объектов SmallClassB.

Несмотря на то, что BigClassA и BigClassB имеют совершенно разные поля, они подвергаются аналогичным операциям с SmallClassA и SmallClassB. Пожалуйста, посмотрите код ниже:

 public class BigClassA {
    // initialize all instance variables to 0
    double totValue     = 0;
    double totGainLoss  = 0;
    SmallClassA[] smallClassArray = new SmallClassA[2];

    public BigClassA(int i, int j) {

        smallClassArray[0] = new SmallClassA(i);
        smallClassArray[1] = new SmallClassA(j);

        for (int k; k<smallClassArray.length; k  ) {
            totValue     = totSmallClassArray[k].getValue();
            totGainLoss  = totSmallClassArray[k].getGainLoss();
        }
    }
}

public class BigClassB {
    // initialize all instance variables to 0
    double totFoo   = 0;
    double totBar   = 0;
    double totPvsNP = 0;
    SmallClassB[] smallClassArray = new SmallClassB[3];

    public BigClassB (int p, int q, int r) {

        smallClassArray[0]  = new SmallClassB(p);
        smallClassArray[1]  = new SmallClassB(q);
        smallClassArray[2]  = new SmallClassB(r);

        for (int k; k<smallClassArray.length; k  ) {
            totFoo       = smallClassArray[k].getFoo();
            totBar       = smallClassArray[k].getBar();
            totPvsNP     = smallClassArray[k].getPvsNP();
        }       
    }
}
 

Я думаю, что цикл for как в BigClassA, так и в BigClassB имеет достаточно схожие характеристики и может быть заменен общим кодом.

Может ли кто-нибудь посоветовать, как создать внешний метод, который может работать как два цикла for, описанных выше, без необходимости повторного написания цикла for для каждого класса? Или, возможно, какие-то другие способы сделать код более кратким? Заранее спасибо за вашу помощь!

Комментарии:

1. Это должно вам помочь.

2. 1. Есть ли в Java8 что-нибудь краткое для перебора массива и суммирования значений getter?

3. @MarounMaroun: Где бы вы представили здесь подклассы?

4. Создайте метод с массивом объектов в качестве параметра и выполните итерацию по массиву объектов. Проверьте наличие экземпляра каждого объекта с желаемым классом и укажите условие if для получения значений.

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

Ответ №1:

Приведенный вами код не содержит достаточно общих частей, чтобы заслуживать такого рефакторинга, но есть способы для этого. Как предложил Марун Марун, вам придется использовать наследование, но есть много шагов :

  • определите общий интерфейс или абстрактный класс между SmallClassA и SmallClassB . В лучшем случае вы будете определять как интерфейс, содержащий все методы с общей сигнатурой, так и абстрактный класс, содержащий общий код.
  • определите общий общий абстрактный класс между BigClassA и BigClassB , параметризованный с помощью <T extends CommonSmallInterface>
  • make class BigClassA extends CommonBigClass<SmallClassA> и то же самое для B

Таким образом, вы избежите дублирования кода ценой определенной сложности.

Примечание: в зависимости от того, как SmallClassA SmallClassB объявлены и, их общий интерфейс и / или суперкласс также могут быть общими.

Ответ №2:

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

Сначала создайте интерфейс

 public interface Summable {
   double getSum(); 
} 
 

Теперь реализуйте этот интерфейс в SmallClassA и SmallClassB. Это переносит большую часть тел цикла на конкретные классы, например, для SmallClassA

 public SmallClassA implements Summable{
    public double getSum() {
       return getValue()   getGainLoss();
    }
}
 

Теперь оба ваших цикла могут быть записаны как

 for ( Summable summable : smallClassArray ) {
   total  = summable.getSum();
}
 

Вы также можете сделать это внешним методом.