Страницы

Поиск по вопросам

среда, 24 октября 2018 г.

Как обращаться к методам класса, заданного динамически?

В текущем классе необходимо программно определять имя другого класса (вида "ClassNumPath + i" ) и далее вызывать его методы.
Файлы классов ClassNumPath0.java (а так же ClassNumPath1.java .. ClassNumPath5.java) существуют и их методы вызываются без ошибок, если обращаться к ним в коде напрямую, например:
ClassNumPath0.initPositions();
или
ClassNumPath4.initPositions();
.. то никаких проблем нет - все работает как надо, отрисовка в onDraw производится и прочее... Но мне нужно определять имя класса ClassNumPathХ динамически и иметь возможность менять это имя имя класса по ходу действия.
Часть кода над которым я бьюсь:
public class ClassNumPath extends SurfaceView implements SurfaceHolder.Callback { ... int currentNum = 5; String currentClassName; Class cClass; ...
@Override protected void onDraw(Canvas canvas) { if (needInitialazation) { currentClassName = "com.mytestapp.testapp.ClassNumPath" + currentNum; cClass = Class.forName(currentClassName);
cClass.initPositions(); // Ошибка: Cannot resolve method 'initPositions()' ClassNumPath5.initPositions(); // А это работает правильно
Log.d("INF", "currentClassName = " + currentClassName); Log.d("INF", "cClass = " + cClass); // Эти логи выдают правильное имя класса com.mytestapp.testapp.ClassNumPath5 } ... cClass.checkState(); // Ошибка: Cannot resolve method 'checkState()' ClassNumPath5.checkState(); // А это работает правильно ... }
Итак, вопрос:
Каким образом можно обращаться к методам класса, чье имя было задано динамически?
Или, пожалуйста, подскажите вариант как по-другому решить задачу. Не хочется выстраивать большую конструкцию с операторами типа Case с выбором нужного имени класса в зависимости от значения currentNum, так как классов ClassNumPathХ может быть более 100 штук.


Ответ

Благодарю @nofate за помощь! Я использовал предложенное им Решение №2 с объявлением интерфейса. Действительно, все методы в пронумерованных классах ClassNumPathX одинаковы и вовсе не обязаны быть статическими. Единственное замечание, в строке:
IClassNumPath classNumPath = (IClassNumPath) clazz.newInstance();
Android Studio выдавал ошибку на IClassNumPath, поэтому я заменил его на название интерфейса ClassNumPath (без префикса I):

В итоге решение получилось такое:
В классе ClassNumPath объявил интерфейс NumPath с набором общих методов для всех нумерованных классов 'ClassNumPathX`
public class ClassNumPath extends SurfaceView implements SurfaceHolder.Callback { ... public static NumPath cNumPath; ... // дать имя ClassNumPath интерфейсу внутри класса ClassNumPath уже нельзя public interface NumPath { void initPositions(); void checkState(); } ... @Override protected void onDraw(Canvas canvas) { if (needInitialazation) { currentClassName = "com.mytestapp.testapp.ClassNumPath" + currentNum; Class clazz = Class.forName(currentClassName); NumPath cNumPath = (NumPath) clazz.newInstance(); cNumPath.initPositions(); } ... // Поскольку cNumPath объявлен как public, то можно пользоваться им в любом месте cNumPath.checkState(); ... } }
В самих нумерованных классах ClassNumPathХ даже и не пришлось ничего особо менять. Только добавил implements ClassNumPath.NumPath и @Override к методам и убрал из них static
public class ClassNumPath4 implements ClassNumPath.NumPath { ... @Override public void initPositions() { ... }
@Override public void checkState() { ... } }

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

Отправить комментарий