Juan-Carlos Gandhi (
juan_gandhi) wrote2007-05-25 05:26 pm
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
new trick
I wonder how obvious or how stupid or how ubiquitous is the following trick:
Say, I have an enum somewhere outside of my realm:
and my method takes an instance of that enum, and I really do not like switching based on the enum; of course I can have an
(PURPLE STUFF ADDED LATER)
Is not it a poetry? :)
Say, I have an enum somewhere outside of my realm:
enum DataType {
PERSONAL, COMMUNITY, PRISON, ARMY;
};
....
and my method takes an instance of that enum, and I really do not like switching based on the enum; of course I can have an
EnumMap
, but the funny trick is that my strategies are based on this enum type, so I can do just this:
enum Strategy {
PERSONAL {
public void process(Entity entity) {...};
},
COMMUNITY {
public void process(Entity entity) {...};
},
PRISON {
public void process(Entity entity) {...};
},
ARMY {
public void process(Entity entity) {...};
}
abstract public void process(Entity entity);
DEFAULT{
public void process(Entity entity) {...};
};
abstract public void process(Entity entity);
(and so on, add functionality here )
Strategy forDataType(DataType type) {
Strategy candidate = valueOf(type.name());
return candidate == null ? DEFAULT : candidate;
}
};
....
Strategy.forDataType(myType).process(myEntity);
(PURPLE STUFF ADDED LATER)
Is not it a poetry? :)
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
Проверка на идентичность enum-ов, а она существенна, при очередном редактировании потерялась.
no subject
no subject
no subject
return (Strategy) Enum.Parse(typeof(Strategy), type.ToString());
no subject
no subject
no subject
no subject
no subject
no subject
Проблема-то в следующем. Нам в метод поступает DataType; надо получить соответствующую стратегию. Ну типа factory вызвать. Ну так эта фабрика-то как работает? А вот я и предложил, как фабрика работает.
no subject
Никаких хаков, никаков поисков перебором, никаких согласований по именам-идентификаторам.
no subject
no subject
no subject
enum DataType { PERSONAL, COMMUNITY, PRISON, ARMY };
enum Strategy { PERSONAL, COMMUNITY, PRISON, ARMY };
Strategy ForDataType(DataType type)
{
return (Strategy)type;
}
I know it's a dirty hack but it works.
no subject
И как же в С# работает вот это место:
(Strategy)type
По порядковому номеру элемента? По имени? Этот кастинг описан в спецификациях языка?
no subject
Запись enum EnumName {...} на самом деле enum EnumName: int {..}. Соответственно, оба enum производные от Int32. Значения нумеруются с 0 и... В общем, дальнейшее понятно.
Хотя я тут подумал... Не совсем я правильно каст написал. Надо бы (Strategy)(int)type писать... Не, проверил - работает.
no subject
Насколько я помню Delphi, там такой кастинг только через приведение к integer работал (во всяком случае, в ранних версиях), и я злился, почему нельзя напрямую, там-то ведь точно число. :)
Но в Java элемент enum - это полноценный объект, а порядковый номер - лишь одно из его полей.
no subject
2. .Net-овский System.Enum - также полноценный объект (корректнее - value type, т. е. объекты создаются на стеке и от enum нельзя создавать производные типы), с кучей методов, реализующий кучу интерфейсов и т.п.
no subject
Зачем потребовалось вводить такой кастинг непосредственно в язык?
Ведь это значит, что, поменяв последовательность элементов в декларации enum, программист рискует получить проблему при приведении типов, в то время как обычно эта операция либо завершается успешно и делает именно то, что ожидали, либо возбуждает runtime exception.
no subject
Вообще говоря, перечисления - настолько низкоуровневая штука, что в прикладной программе их быть не должно. Полиморфизм-то не зря придумывали.
no subject
no subject
no subject
Вся прелесть .Net-овских перечислений в том, что они ссылочные, т.е. очень дешевые с точки зрения памяти и GC. Методов не накидаешь, правда, зато вышеописанный трюк, что в .Net, что в старой Жаве, что без enum-ов, легко реализуется (и именно так, как вы написали), описан у Бека, и называется pluggable selector.
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
Во-вторых, я не понимаю, что "поэтического" в решении этой задачи в лоб.
no subject
Ведь это ж вечная проблема - mapping.
no subject
Быстродействие, связанное с перебором внутри valueOf(), игнорируем. Понятно, что количество элементов будет измеряется десятками, да и время выполнения стратегии достточно велико, чтобы время выбора стратегии было несущественно.
Но синтаксически не очень красиво смотрится размещение кода внутри enum. Для компактности Strategy.process() может вызывать один из методов personal(), community() и т.п. Но в таком случае, наверное, проще искать нужный метод через рефлексию, обойдясь без лишнего enum и встроив этот поиск прямо в process().
no subject
Recently I enjoyed learning about java.lang.reflect.Proxy that allows one to construct classes on the fly.
no subject
no subject
I can imagine a fully static class construction path, either via bytecode assembler or by full-blown java source generation and complilation, and then loading the class file. I could imagine Guice to work this way :)
But to quote project homepage, "Guice cures tight coupling," "Guice is the anti-static." This all sounds pretty to my dynamic-languages-inclined ear :)
no subject
no subject
На дадаизм похоже, да. :-)
Проблема в том, что если кто-то outside of your realm добавит новое значение в enum DataType, то статическими методами этого обнаружить нельзя, и результатом будет исключение в процессе исполнения.
"Uncaught java.lang.InvalidCast exception in class mil.NORAD.ControlLoop, commencing emergency launch."
no subject
no subject
no subject
no subject
no subject
no subject
no subject
Вот задача. Есть независимая сущность, данная нам в именах. В принципе, юзеру пофиг, строки это, числа, набор сингтонов. Просто есть набор, он ограничен и неизменен.
Теперь, юзеру нужно запрограммировать действия, зависящие от этих самых сущностей. Если бы функции были законными элементами языка, и если бы нужно было типа по паре функций на сущность, то можно было бы ограничиться двумя таблицами. Скажем, как на джаваскрипте:
no subject
Обсуждаемый юзер точно знает, какой тип на какую стратегию отображается, ибо он сам эти стратегии и кодирует. Следовательно, речь идёт вовсе не обо "всех входных вариантах", которым несть числа, и где было бы полезно некое автоматизированное нахождение соответствия, как у Вас с совпадающими именами enum.
Что мы вообще обсуждаем - как изящно записать это отображение, используя только синтаксис Java (т.е. конфигурационные файлы не годятся)?
no subject
Strategy getStrategy(void)
и реализовать его очевидным образом для каждого значения. Потом
data.getStrategy().process(entity);
Всё статически типизировано. Насколько я понимаю, вам нужно решение, которое не меняет DataType ("I have an enum somewhere outside of my realm"), но это по сути значит, что просто нет общего дизайна.
no subject
Ну даже если бы. DataType не должен никакого понятия иметь о своих будущих юскейсах. Мало ли кто где использует; на всяк чих не наздоровкаешься.
no subject
no subject