#java
#java
Вопрос:
У меня есть некоторый код, который нуждается в сокращении, и это было рекомендовано мне на Reddit.com для этого я использую функции. Но проблема в том, что код в основном представляет собой набор public static final
«ссылок», таких как PIXELS_PER_INCH = 72
.
Я открываю исходные коды своего приложения на GitHub, если кто-то хочет взглянуть на это таким образом.
Вот пример того, как я присваиваю значения своим константам:
public static final int PICTURES_4 = 0;
public static final int PICTURES_6 = 1;
public static final int PICTURES_8 = 2;
public static final int PICTURES_10 = 3;
public static final int PICTURES_12 = 4;
public static final int PICTURES_OPTION_0 = 4;
public static final int PICTURES_OPTION_1 = 6;
public static final int PICTURES_OPTION_2 = 8;
public static final int PICTURES_OPTION_3 = 10;
И вот пример того, где я использую эти постоянные ссылки:
switch (settings.getInt(SettingsActivity.PICTURES_OPTION, SettingsActivity.DEFAULT_PICTURES_OPTION)) {
case SettingsActivity.PICTURES_4:
totalImages = SettingsActivity.PICTURES_OPTION_0;
break;
case SettingsActivity.PICTURES_6:
totalImages = SettingsActivity.PICTURES_OPTION_1;
break;
case SettingsActivity.PICTURES_8:
totalImages = SettingsActivity.PICTURES_OPTION_2;
break;
По сути, я хотел бы знать, как использовать функцию для сокращения кода, но при этом сохранить возможность использовать читаемые ссылки. Или моя идея использовать читаемую ссылку неверна? На онлайн-уроке программирования я узнал об использовании констант в качестве читаемых ссылок (таких как PIXELS_PER_INCH = 72) вместо использования абсолютных значений.
Спасибо, что уделили мне время.
Обновление: В итоге я воспользовался предложениями aioobe и Ллойда Озимандиаса Форса. Я использовал EnumMap
в цикле for. Однако в цикле for я по какой-то причине не смог использовать myEnumMap.values()
. Я погуглил это и нашел другой способ сделать это с помощью myEnumMap.class.getEnumConstants()
, вместо этого.
Комментарии:
1. Хотя константа PIXELS_PER_INCH в порядке, остальные из этих констант, похоже, заменяют одно магическое число на другое.
2. @Paul Butcher: Спасибо за ваш ответ. Я создал код таким образом, потому что считал удобочитаемость одним из наиболее важных аспектов программирования. Я хотел, чтобы читатели моего кода поняли, что я делал в своем операторе switch. Но выполнение этого таким образом сделало код слишком длинным, и читатели жалуются на это. Есть ли у вас какие-либо рекомендации по сохранению удобочитаемости при сокращении кода?
3. Не беспокойтесь о сокращении кода, подумайте о повышении удобочитаемости. Я не понимаю, почему этот переключатель / регистр преобразует (например) PICTURE_18 (7) в PICTURE_OPTION_7 (18). Что означают все эти цифры и какой цели вы пытаетесь достичь, переводя между ними? Попытайтесь выразить это намерение в коде.
4. Читаемость / понятность, безусловно, важны. И хотя макет хорош, все, что я (например) могу сказать, это то, что
PICTURES_6
подразумеваетPICTURES_OPTION_1
. Это бессмысленно. Дайте константам лучшие имена, такие какPICTURE_OPTION_RESIZE
иSAVE_BUTTON_ICON
, и читаемость значительно улучшится.5. @Paul Butcher, @Andrzej Doyle, @aioobe, @Lloyd Ozymandias Сила: В моем приложении используется виджет для Android, называемый spinner. По сути, это выпадающее меню. Я вызываю метод get из счетчика, который возвращает число из списка на основе 0, представляющее опцию, выбранную в меню. Выбранный параметр — это просто число, и его нелегко прочитать. Итак, я создал константы, которые пытаются объяснить значение выбранной опции. Если пользователь выбирает вариант 1, это PICTURE_OPTION_0, а значение — PICTURE_4, потому что вариант 1 — это 4 картинки.
Ответ №1:
-
Вы можете поместить параметры в map и сделать
get(option)
вместоswitch(option)
Инициализируйте карту следующим образом:
Map<Integer, Integer> optionsMap = new HashMap<Integer, Integer>() {{ put(SettingsActivity.PICTURES_4, SettingsActivity.PICTURES_OPTION_0); put(SettingsActivity.PICTURES_6, SettingsActivity.PICTURES_OPTION_1); ... }};
а затем замените переключатель следующим образом:
totalImages = optionsMap.get(settings.getInt(SettingsActivity.PICTURES_OPTION, SettingsActivity.DEFAULT_PICTURES_OPTION));
-
Или (поскольку у вас, похоже, простое преобразование целого числа в целое) вы могли бы поместить свои значения в таблицу поиска.
-
Или вы можете поместить это в функцию и заменить все разрывы возвратами:
public int getPictureOption() { switch (settings.getInt(SettingsActivity.PICTURES_OPTION, SettingsActivity.DEFAULT_PICTURES_OPTION)) { case SettingsActivity.PICTURES_4: return SettingsActivity.PICTURES_OPTION_0; case SettingsActivity.PICTURES_6: return SettingsActivity.PICTURES_OPTION_1; case SettingsActivity.PICTURES_8: return SettingsActivity.PICTURES_OPTION_2; } }
а затем выполните
totalImages = getPictureOption();
Если вы считаете, что ваши константы говорят сами за себя, вы могли бы избавиться от всех SettingsActivity.
, добавив статический импорт в начало вашего файла:
import static your.package.SettingsActivity.*;
Комментарии:
1. Спасибо за ваш ответ. Люди, которым я показывал свой код, сказали, что мои инструкции switch слишком длинные. В реальном коде мои операторы switch имеют длину около 16 операторов case, поскольку код PICTURES_# и PICTURES_OPTION_ # продолжается. Мне было интересно, смогу ли я сохранить читаемость своего кода при использовании функции для сокращения кода. Удобочитаемость с точки зрения «что делает этот оператор switch?» С длинной версией кода несколько легче понять, что происходит, но она слишком длинная.
2. Обновлен первый вариант в моем ответе.
3. Я думаю, что помещу свои константы в EnumMap и воспользуюсь вашим первым предложением. Спасибо за вашу помощь.
Ответ №2:
Не включайте значения enum — это задание для полиморфизма или таблицы Map / look up, как упоминалось aiobe.
Чтобы проиллюстрировать один из методов работы с перечислениями в Java, рассмотрим следующий параметр SettingsActivity enum с полиморфным методом getPictureOption() . Он объявлен абстрактным в теле перечисления, заставляя каждую константу перечисления реализовывать этот метод. Этот метод более подробно описан в Effective Java 2nd Edition (Джош Блох).
enum SettingsActivity {
OPTION_1(){
public int getPicureOption() {
return myValue * 6;
}
},
OPTION_2(){
public int getPictureOption() {
return Math.pow(myValue,5);
}
},
...
OPTION_N() {
public int getPictureOption() {
return myValue-6;
}
};
private final int myValue;
private SettingsActivity(int myValue) {
this.myValue = myValue;
}
// enums can have abstract methods!
public abstract int getPictureOption();
}
SettingsActivity foo = getSettingsActivityFromSomewhere();
// polymorphic getPictureOption method - we don't
// know which activity was clicked
int something = foo.getPictureOption();
Конечно, это всего лишь пример кода, иллюстрирующий, что вы можете сделать. Я не уверен, какова цель вашего оператора switch или откуда взято перечисление SettingsActivity, поэтому я не могу предложить больше рекомендаций.
В случае, если вы хотите использовать Map, класс EnumMap, предоставляемый JDK, предоставляет сверхэффективную реализацию Map для перечислений (он реализован в виде одного длинного значения для перечислений с менее чем 65 константами и массива длинных значений для > 64 констант). В любом случае, операции поиска равны O (1) (в отличие от O (lg n) для хэш-карты).
Комментарии:
1. Спасибо за ваш ответ. На самом деле, SettingsActivity не является перечислением. Это класс, а константы являются статическими константами (такими как PICTURES_#). Это был единственный известный мне способ получить доступ к переменной из одного класса, находясь в другом классе.
2. Спасибо за ваше предложение использовать EnumMap. Я воспользуюсь этим и первым предложением aioobe.