Java: как попроще сделать вызов метода по имени?
Правильно ли я понима, что объект класса A = new Object ? И вызов будет в зависимости от имени переменной А?
Примерно такого хочется
Object A = new Object;
A.onClick; // ничего или по умолчанию
A.name = "A";
A.onClick; // выполнится functionA
Устроит и static OnClick (String objName). Т.е. по сути задача вызвать функцию по её имени.
enum Enum {
A {
@Override
public void onClick {
// ...
}
};
public abstract void onClick;
public static void onClick(String objName) {
valueOf(objName).onClick;
}
}
?
P.S. То, что надо.
Внутри Enum.onClick видимо не отловить
enum Enum {
A {
@Override
public void onClick {
// ...
}
};
private static final java.util.HashMap<String, Enum> map = new java.util.HashMap<>
static {
for (Enum e : values {
map.put(e.name e);
}
}
public abstract void onClick;
public static void onClick(String objName) {
Enum e = map.get(objName);
if (e == null) {
throw new RuntimeException("unexpected name");
}
e.onClick;
}
}
Хотя OnClick вообще пустой поставил, т.е. обращение к элементам списка нет.
Можно конечно вызов Enum.OnClick(obj) снаружи (в классе Object) обернуть проверкой наличия objName в Enum, и если есть, то вызвать.
В принципе пойдет и так...
Блин, у меня в коде косяк был.
Вообще, можно сделать HashMap или бор <String, ISingleMethod>
Если разные классы создавать не получается, то в зависимости от имени в конструкторе\онклике слукапить один раз нужный комманд, положить в поле, и потом его все время вызывать.
Енум, в прниципе это и делает, только лукап каждый раз происходит, и енумы все-таки не для этого предназначены. Тот, кто это увидит, скажет - втф?
то в зависимости от имени в конструкторе\онклике слукапить один раз нужный коммандоткуда слукапить? Все-равно ты где-то пропишешь соответствие [строка Name]->[инстанс полиморфного типа]. Топикстартер, собственно, и спрашивал как это соответствие прописать switch-ем в лоб, заполнение HashMap-а, рефлекшеном или еще как? Енам позволяет получить это соответствие нахаляву, поэтому вариант с енамом лучший.
Дизайн кривой.
Если [строка Name] приходит как строка во внешнем параметре, то нормальный дизайн. Если это "магические" строки только в коде, то, да, кривой.
Дизайн кривой. Для таких вещей полиморфизм придуман былКаждый объект (более 50) в системе имеет свой уникальный обработчик (пишу нестандартную игру). Зачем плодить 100500 классов? Фен-шуй мне не нужен, а вот минимальное количество кода и удобство правки - очень даже.
Вариантом было прилепить скриптовый язык какой, но это лишний оверхеад.
Через Enum весьма неплохой вариант получился. Таким образом всю логику реакции на события вынес в отдельный файл. Меня устраивает.
, добавление методов в данной реализации мне не понравилось. В случае с Enum просто добавляю объект, напр. B в Enum, и прописываю ему нужные методы.
Енам позволяет получить это соответствие нахаляву, поэтому вариант с енамом лучший.Правда есть небольшой минус find usages для членов енама не полный результат будет выдввать, и можно решить, например, что член енама не используется, удалить и получить ошибку в рантайме. В прямолинейном варианте через switch такого нет.
Таким образом всю логику реакции на события вынес в отдельный файл. Меня устраивает.и чем это стало удобнее?
кусочек такого файла можно посмотреть?
Сводить тред - "а ты не правильно программируешь" - зачем? Мне не требуется расширяемый-поддерживаемый-удобо-читаемый-код. Мне требуется удобство для меня в первую очередь на том этапе моих знаний, коими я владею в настоящий момент. Пусть их мало, но для задуманного надеюсь их хватит.
Зачем плодить 100500 классов?Но в варианте ты именно этим и занимаешься.
минимальное количество кода и удобство правки ... Таким образом всю логику реакции на события вынес в отдельный файл.Это вообще взаимоисключающие параграфы. Один файл, в котором описаны все 50 обработчиков, да ещё и со своими данными, не может быть удобным.
пишу нестандартную игру
Enum.valueOf может за O(N) работать, да ещё и строки всё время сравнивает, для игры такой метод может не подойти по производительности.
В твоём случае вообще не понятно, зачем использовать строковые имена. Почему вместо new GameObject("A") сразу не написать new GameObject(new BehaviorA или new GameObject(Behaviors.A)?
Фен-шуй мне не нужен, а вот минимальное количество кода и удобство правки - очень даже.
Мне не требуется расширяемый-поддерживаемый-удобо-читаемый-код.
Но в варианте ты именно этим и занимаешься.Надо было написать вместо кучи классов - кучу файлов, чтобы смысл был понятен?
Это вообще взаимоисключающие параграфы. Один файл, в котором описаны все 50 обработчиков, да ещё и со своими данными, не может быть удобным.Тебе виднее
Enum.valueOf может за O(N) работать, да ещё и строки всё время сравнивает, для игры такой метод может не подойти по производительности.Возникновение событий редкое явление и будет вызов через 5мс или 200мс не принципиально.
В твоём случае вообще не понятно, зачем использовать строковые имена. Почему вместо new GameObject("A") сразу не написать new GameObject(new BehaviorA или new GameObject(Behaviors.A)?Много загадочных вещей можно увидеть в коде, если автор плохо знает язык. И чего теперь сидеть читать литературу по Java, пока желание что-либо делать не пропадет, либо пытаться сделать что-то? Код никто кроме меня не увидит, так что не все ли равно как будет написано?
Надо было написать вместо кучи классов - кучу файлов, чтобы смысл был понятен?Нет, смысл не стал бы понятен, потому что кучу классов можно написать в одном файле.
Много загадочных вещей можно увидеть в коде, если автор плохо знает язык. И чего теперь сидеть читать литературу по Java, пока желание что-либо делать не пропадет, либо пытаться сделать что-то? Код никто кроме меня не увидит, так что не все ли равно как будет написано?Желание что-либо делать частенько пропадает, когда твои руки запутались в жирном спагетти. Я задал вполне уместный вопрос, почему бы тебе не сделать new GameObject... Это могло бы облегчить задачу, разве ты не за этим сюда написал?
Предпочитаю разгребать код когда требуется, а не оптимизировать заранее пока проблемы нет.
Использую уже готовый движок libgdx, так что почти кода как такового будет мало - в основном это будет описание вызовов событий.
Объекты будут грузиться из XML-файла и для удобства id-объекта строка. Поэтому мне видится наиболее логичным связывать строку-id и функцию.Зачем это делать в рантайме? Наиболее логично связать строку с именем класса, который реализует поведение.
Предпочитаю разгребать код когда требуется, а не оптимизировать заранее пока проблемы нет.Никто не говорил про оптимизацию, речь идёт о том, как наиболее просто и быстро решить задачу.
Зачем это делать в рантайме? Наиболее логично связать строку с именем класса, который реализует поведение.Лично мне удобнее хранить объекты именно в XML, чем в Java-коде.
В данном случае возможна привязка не в рантайме?
В данном случае возможна привязка не в рантайме?Я не ясно выразился. Речь шла о том, что связать строку и объект-поведение можно один раз.
1. Определяется интерфейс ICommand
2. Создаются классы, реализующие ICommand, и содержащие логику реакций на события.
3. При создании объекта неким образом (каким?) определяем, что вот этому объекту надо сопоставить вот этот метод.
4. В работе программы вызывать объект.Command
?
2. Создаются классы, реализующие ICommand, и содержащие логику реакций на события.Не обязательно, но можно и так. Всё зависит от конкретной задачи.
3. При создании объекта неким образом (каким?) определяем, что вот этому объекту надо сопоставить вот этот метод.Как угодно, например, полное имя класса через Reflection.
Зачем давать советы, которыми заведомо нельзя воспользоваться? Потешить самомнение что ли?
Зачем давать советы, которыми заведомо нельзя воспользоваться? Потешить самомнение что ли?Я не понял, каким именно из советов нельзя воспользоваться?
Не обязательно, но можно и так. Всё зависит от конкретной задачи.На данный момент я делаю вообще чтобы хоть как-нибудь работало, а не выбираю - сделать через интерфейс или по другому.
Как угодно, например, полное имя класса через Reflection.
Про Reflection просто знаю, что есть такое, а вот пользоваться не доводилось.
Разбираться с этим, чтобы выиграть сэкономить несколько мс, зачем? Решение задачи получил и оно уже у меня работает.
В общем, я согласен с Майком. Вот, например, как я делаю ачивки в своём порте RoboZZle на андроид:
Есть абстрактный класс ачивок с парой методов - isDone и getRelatedPuzzles, а также полями с именем и иконкой.
Дальше по классу-наследнику на ачивку. Некоторые ачивки наследуют от вспомогательных классов.
Список всех ачивок хранится в коде в виде массива, который заполняется в статическом конструкторе класса Achievements.
Ну и всё. Никаких свитчей и словарей. Экран ачивок просто показывает элементы списка. И при решении паззла пересчитывается состояние всех ачивок.
Если, конечно, тебе не надо уметь сущности в игре настраивать через него руками.Именно руками и настраиваю. В коде указывать кто, где стоит, какие атрибуты имеет - не хочу.
я делаю ачивки в своём портеВ том вся и загвоздка, что обработчики уникальные полностью, т.е. по клику на один предмет будет выход из игры, по клику на другой проигрываться монолог, а по клику по третьему на сцену добавляться новый предмет. Одинаковых не будет, ибо все предметы уникальны (игра экспериментальная).
Зачем плодить 100500 классов?Enum это и есть класс. Непонятно, что ты пытаешься сэкономить.
500 классов можно в одном файле тоже задать, если так уж хочется.
Разбираться с этим, чтобы выиграть сэкономить несколько мс, зачем? Решение задачи получил и оно уже у меня работает.Ты спросил - тебе ответили. Если тебе сойдет и так - то окей, дело твое.
Если бы я мог это сделать, то данной темы не было бы.
для удобства id-объекта строкаДля удобства добавить в xml еще одно поле с именем класса не?
Для удобства добавить в xml еще одно поле с именем класса не?Не.
Это троллинг какой что ли? Очевидно же, что знаю Яву весьма поверхностно, иначе этого вопроса и не было бы.
Зачем предлагать мне то, что я не смогу реализовать или что потребует дополнительного изучения?
Я ленивый и, если уже найден работающий код, то зачем что-то еще учить, если можно дальше продолжить писать код?
Тем более, что место не критичное.
Ладно, я понял, написал и ладно... Удачи!
Правильно иметь два разных подкласса твоего обджекта.Я бы в контексте треда спросил, как джавоверно поступать, если заранее неизвестно, чему равно два, а станет известно только в рантайме.
минимальное количество кода и удобство правки - очень даже.Вариантом было бы перейти с джавы на язык, минимизирующий количество кода.
Вариантом было прилепить скриптовый язык какой, но это лишний оверхеад.
Вариантом было бы перейти с джавы на язык, минимизирующий количество кода.Неверно, в данном случае вариантом было бы перейти с libgdx на Unity.
Всмысле в рантайме? Код тоже возьмется в рантайме?
Не код. Процедура.
Код тоже возьмется в рантайме?Вы говорите так, словно генерить байткод на лету - это что-то плохое
Да нет, почему сразу плохое. Просто так как в джаве процедуры не first-level citizen'ы, то там не то что бы много вариантов, куда можно засунуть сгенеренный байткод.
Есть рефлекшен \ Fast* (CGLIB который жрет сотни-десятки us.
Хочется быстрее - компилируй код.
Но ты это все и сам, наверное, знаешь. К чему вопрос то?
К чему вопрос то?Ну к тому, что интересно, как ни странно.
Как в плюсах сделать динамические свойства и методы, я примерно представляю.
Думал, есть ли в джаве распространенные techniques.
Думал, есть ли в джаве распространенные techniques.Есть. Взять groovy.
ASM. Поверх него можно писать свои какие-то штуки. В основном используется для каких-нибудь хаков, типа генерации хитрых проксей, моков и так далее.
У джавы есть кривоватенький апи для доступа к javac в рантайме.
Можно и упомянутые выше груви/биншеллы юзать, но там свои проблемы.
Есть довольно низкоуровневый У джавы есть кривоватенький апи для доступа к javac в рантайме.
Можно и упомянутые выше груви/биншеллы юзать, но там свои проблемы.
Оставить комментарий
0000
Допустим есть класс Objectи два объекта этого класса, напр. A и B с именами "A" и "B".
В зависимости от имени хочется выполнять различные команды (зависимость имя - набор команд один к одному).
Вижу несколько вариантов
1. Прописать всё в OnClick через switch
Получится огромный switch (объектов достаточно много и действия различны, т.е. обычное наследование не катит).
2. Через Reflection вызвать метод "function" + Object.name по имени
Как еще можно? Желательно как можно меньше кода. На правильность/общность/поддерживаемость кода наплевать (пишу для себя).
В идеале хотелось бы все functionA, functionB в отдельном классе. Видимо как статичные методы.
P. S. Время доступа так же не сильно важно, поскольку события вызываются относительно редко.