new trick

May. 25th, 2007 05:26 pm
juan_gandhi: (Default)
[personal profile] juan_gandhi
I wonder how obvious or how stupid or how ubiquitous is the following trick:

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? :)

Date: 2007-05-26 02:17 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
How would you use cast here? (And, again, what's wrong with this kind of reflection?)

Date: 2007-05-26 03:15 pm (UTC)
From: [identity profile] http://users.livejournal.com/d_m_/
Там не совсем reflection, но поиск элемента по имени, причём путём полного перебора элементов enum #1. В настоящем mapping всё-таки есть хеширование. Но если автору так не нравится Map, почему бы не делать так, как положено, т.е. в каждый элемент enum #2 поместить элемент из enum #1, задавая эту связь в конструкторе? И работает шустрее некуда, и assert не просит :)

Date: 2007-05-26 06:38 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
В каком конструкторе?

Проблема-то в следующем. Нам в метод поступает DataType; надо получить соответствующую стратегию. Ну типа factory вызвать. Ну так эта фабрика-то как работает? А вот я и предложил, как фабрика работает.

Date: 2007-05-26 08:04 pm (UTC)
From: [identity profile] http://users.livejournal.com/d_m_/
Я имел в виду вот что:
enum Strategy { 
  PERSONAL,  COMMUNITY, PRISON, ARMY;
};

enum DateType {
  
  PERSONAL(Strategy.PERSONAL),  
  COMMUNITY(Strategy.COMMUNITY),  
  PRISON(Strategy.PRISON),  
  ARMY(Strategy.ARMY);  
 
  private Strategy strategy;
  private DataType( Strategy strategy){this.strategy=strategy};

  public static strategyForType(DataType type){return type.strategy};
  public getStrategy(){return strategy};
}


Никаких хаков, никаков поисков перебором, никаких согласований по именам-идентификаторам.

Date: 2007-05-26 10:03 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
Да это очевидное решение если мы хотим добавить зависимость DataType от Strategy. Что очень неестественно.

Date: 2007-05-26 10:06 pm (UTC)
From: [identity profile] http://users.livejournal.com/d_m_/
Ок, теперь я уже вижу первую фразу поста :)

Date: 2007-05-26 05:31 pm (UTC)
From: [identity profile] pvax.livejournal.com
Not in Java, of course. In C#:

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.

Date: 2007-05-26 05:48 pm (UTC)
From: [identity profile] http://users.livejournal.com/d_m_/
Ничего себе!
И как же в С# работает вот это место:
(Strategy)type
По порядковому номеру элемента? По имени? Этот кастинг описан в спецификациях языка?

Date: 2007-05-26 06:12 pm (UTC)
From: [identity profile] pvax.livejournal.com
Я же говорю - хак. Но документированный.
Запись enum EnumName {...} на самом деле enum EnumName: int {..}. Соответственно, оба enum производные от Int32. Значения нумеруются с 0 и... В общем, дальнейшее понятно.
Хотя я тут подумал... Не совсем я правильно каст написал. Надо бы (Strategy)(int)type писать... Не, проверил - работает.

Date: 2007-05-26 08:09 pm (UTC)
From: [identity profile] http://users.livejournal.com/d_m_/
Тогда понятно. И хак только в неявном преобразовании к int.

Насколько я помню Delphi, там такой кастинг только через приведение к integer работал (во всяком случае, в ранних версиях), и я злился, почему нельзя напрямую, там-то ведь точно число. :)

Но в Java элемент enum - это полноценный объект, а порядковый номер - лишь одно из его полей.

Date: 2007-05-27 06:58 am (UTC)
From: [identity profile] pvax.livejournal.com
1. (Не)явного преобразования к System.Int32 нет. В IL выполняется инструкция castclass, один раз, а не 2.
2. .Net-овский System.Enum - также полноценный объект (корректнее - value type, т. е. объекты создаются на стеке и от enum нельзя создавать производные типы), с кучей методов, реализующий кучу интерфейсов и т.п.

Date: 2007-05-27 10:53 am (UTC)
From: [identity profile] http://users.livejournal.com/d_m_/
Вот за такие трюки, документированные хаки, я и не люблю C#.
Зачем потребовалось вводить такой кастинг непосредственно в язык?
Ведь это значит, что, поменяв последовательность элементов в декларации enum, программист рискует получить проблему при приведении типов, в то время как обычно эта операция либо завершается успешно и делает именно то, что ожидали, либо возбуждает runtime exception.

Date: 2007-05-28 04:13 pm (UTC)
From: [identity profile] pvax.livejournal.com
Во-первых, с C# такого приведения типов нет, это все свойства платформы. Во-вторых, в описанном случае при перемене порядка элементов их значения действительно меняются. Если хочется жестко привязать, то можно сделать что-то вроде: enum Blah { None=0, Undefined=1, Unknown=2, Empty=3, Dummy=4, WTF=5 } а потом тасовать, как пожелается. Ну, плюс еще есть фишка удобная, добавить к enum атрибут [Flags] и над ним можно будет логические операции проделывать :)
Вообще говоря, перечисления - настолько низкоуровневая штука, что в прикладной программе их быть не должно. Полиморфизм-то не зря придумывали.

Date: 2007-05-26 06:39 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
Такое ощущение, что главного-то джавного цимеса никто не знает просто. Добавим сейчас.

Date: 2007-05-26 11:33 pm (UTC)
From: [identity profile] selfmade.livejournal.com
В смысле, что в Java в enum можно напихать методов? Да, такого в C# вроде нету.

Date: 2007-05-27 07:06 am (UTC)
From: [identity profile] pvax.livejournal.com
Гм, в Жаве перечисления ссылочные или по значению?
Вся прелесть .Net-овских перечислений в том, что они ссылочные, т.е. очень дешевые с точки зрения памяти и GC. Методов не накидаешь, правда, зато вышеописанный трюк, что в .Net, что в старой Жаве, что без enum-ов, легко реализуется (и именно так, как вы написали), описан у Бека, и называется pluggable selector.

Date: 2007-05-28 05:07 am (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
Я не уверен, что понял вопрос, но, думаю, правильный ответ будет - ссылочные. :) Но имеют и значения, и могут быть перечислены.

Date: 2007-05-28 04:09 pm (UTC)
From: [identity profile] pvax.livejournal.com
Ссылочные типы и типы (передаваемые) по значению - терминология .Net. Объекты ссылочного типа создаются в куче и подлежат сборке мусора. Объекты по значению создаются на стеке и сборке мусора не подлежат. И те, и те - объекты.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

May 2025

S M T W T F S
    1 2 3
456 7 8 9 10
11 121314151617
181920 21 222324
25 262728 293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 30th, 2025 02:11 am
Powered by Dreamwidth Studios