Как связать массивы с методами - PullRequest
0 голосов
/ 31 декабря 2018

Этот вопрос в основном относится к Java, но если он работает для всех языков объектно-ориентированного программирования, тогда это хорошо.

Мне интересно, есть ли способ связать значение массива с определенным методом.У меня есть программа с многочисленными методами, и метод запускается, когда в гигантском сценарии if существует определенное условие.Я нахожу это медленным и неэффективным.Мне было интересно, смогу ли я создать массив, в котором каждое значение ссылается на соответствующий метод для выполнения.

Например: если у меня есть число от 0 до 99, и я хочу запустить определенный метод на основелюбой номер, который я выберу.Вместо создания сценария if со 100 различными случаями, могу ли я создать массив с соответствующим методом?Все методы находятся в одном классе, и у каждого числа есть свой собственный метод.Это будет выглядеть примерно так:

int num = 73;
methods[num](parameters);

Я не знаю, возможно ли что-то подобное.Любая помощь с благодарностью!

Ответы [ 7 ]

0 голосов
/ 31 декабря 2018

Мне интересно, есть ли способ связать значение массива с определенным методом.

Вы можете использовать отражение для генерации массива методов.Тем не менее, это «не идеальное решение», потому что оно затруднит поддержку вашего кода.Итак, я должен сказать, что это нехорошая практика, но вот она.

package methodarray;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodArray {
    public static void main(String[] args) {
        Method[] arrayOfMethods = new Method[100];
        try {
            //...You will need to add the methods by their name, you can use for loops to add them quickly
            arrayOfMethods[1] = MethodArray.class.getDeclaredMethod("someMethodName");
            arrayOfMethods[2] = MethodArray.class.getDeclaredMethod("someOtherMethod");
            //...
        } catch (NoSuchMethodException | SecurityException ex) {
            //this can throw an Exception if the method is not found, handle it here
        }
        //now to call a method from the array just do
        try {
            arrayOfMethods[1].invoke(MethodArray.class);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            //...handle exceptions
        }
    }

    public void someMethodName(){
        //...logic
    }

    public void someOtherMethod(){
        //...logic
    }
}

Это поможет вам вызывать методы так, как вы хотите, но имейте в виду, что для безопасности java может вызвать несколько ожиданий, когдаиспользуя отражение.Чтобы отправить дополнительные аргументы, просто наберите arrayOfMethods[n].invoke(MethodArray.class, args[]);

Этот вопрос в основном относится к Java, но если он работает для всех языков объектно-ориентированного программирования, тогда это хорошо.

ДляПри решении этих общих сценариев мы используем Шаблоны проектирования , шаблоны - это проверенные решения для общих сценариев.Все ответы о том, что вы должны «использовать интерфейс», на самом деле пытаются помочь вам в достижении этого, шаблон, который вы можете использовать, называется Command Pattern, вы можете прочитать об этом здесь .Понимание или чтение шаблона может быть бесполезным, поскольку вы сказали, что не знакомы с использованием интерфейсов.(Лично я всегда рекомендую Head First Design Patterns как вводную книгу по шаблонам.)

Как только вы поймете шаблон команд, вы можете просто сгенерировать массив команд, это лучшее ОО-решение, имейте это в виду.Я не буду приводить пример, потому что я думаю, что это трудно понять, если у вас нет четкого представления о том, как использовать интерфейсы, прочитайте о них, это будет стоить того! *

0 голосов
/ 31 декабря 2018

Вам нужно передать объект класса, в котором определен метод, получить имя метода из массива и передать аргументы.Размещаем только необходимый код.

public static Object invokeExactMethod(Object object, String methodName, Object... args) {
        if (null == args) {
            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
        }
        int arguments = args.length;
        Class<?>[] parameterTypes = new Class[arguments];
        for (int i = 0; i < arguments; i++) {
            parameterTypes[i] = args[i].getClass();
        }
        return invokeExactMethod(object, methodName, args, parameterTypes);
    }


    invokeExactMethod() is method provided my MethodUtils class of apache commons.

Надеюсь, это поможет .. !!

0 голосов
/ 31 декабря 2018

в дополнение к ответу JB Nizet, могут использоваться другие варианты синтаксиса:

    this.tasks = new ScriptTask[4];
    this.tasks[0] = this::foo;
    this.tasks[1] = this::bar;
    this.tasks[2] = (String s, int i) -> {
        System.out.println(s);
    };
    this.tasks[3] = (String s, int i) -> System.out.println(s);

или даже:

   this.tasks = new ScriptTask[] {
        this::foo,
        this::bar,
        (String s, int i) -> {
            System.out.println(s);
        },
        (String s, int i) -> System.out.println(s)
    };
0 голосов
/ 31 декабря 2018

Что ж, я думаю, что мы можем использовать Reflection для достижения этой цели следующим образом: "

1.) Класс для хранения информации о методах

public class MethodInfo {

    public String methodName;
    public Class<?>[] params;
}

2.) Класссостоящий из всех методов

public class Task {

    public void method1(int x, ......){

    }
    And So On..
}

3.) Основной класс создает массив и использует его. Здесь с помощью Reflection мы можем получить доступ к методам из массива и вызвать их.

public class MainClass {

    public static void main(String[] args) {

        MethodInfo firstMethod = new MethodInfo();
        firstMethod.methodName = "method1";
        firstMethod.params = Array OF Parameter Types(.class values)

        MethodInfo[] methods = new MethodInfo[10];
        methods[1] = firstMethod;

        java.lang.reflect.Method method = Task.class.getMethod(methods[1].methodName, methods[1].params);
        method.invoke(new Task(), param1, param2,....);
    }
}
0 голосов
/ 31 декабря 2018

Может создать интерфейс для сохранения методов для запуска, например:

public interface MethodRunner {
   public void run();
} 

Определить массив и добавить экземпляр MethodRunner.

MethodRunner[] methodsRunners = new MethodRunner[n];
methodsRunners[0] = new MethodRunner() {
      @Override
      public void run() {
        // some method here 
      }
};
methodsRunners[0] = ... 
      . 
      . 
methodsRunners[n] = ... 

И запустите его следующим образом:

methodsRunners[n].run();
0 голосов
/ 31 декабря 2018

Определить интерфейс (назовем его ScriptTask), определяющий метод для выполнения (назовем его execute).Создать массив задач из ScriptTask.Затем используйте tasks[num].execute(parameters).

Пример:

@FunctionalInterface
interface ScriptTask {
    void execute(String s, int i);
}

class Script {

    private ScriptTask[] tasks;

    Script() {
        this.tasks = new ScriptTask[2];
        this.tasks[0] = this::foo;
        this.tasks[1] = this::bar;
    }

    private void foo(String s, int i) {
        System.out.println(s);
    }

    private void bar(String s, int i) {
        System.out.println(i);
    }

    void run() {
        for (int i = 0; i < tasks.length; i++) {
            tasks[i].execute("hello", i);
        }
    }

    public static void main(String[] args) {
        new Script().run();
    }
}

Обратите внимание, что если у вас действительно есть 100 различных методов в одном классе, это явный признак того, что его следует реорганизовать в несколько более простыхклассы, которые легче читать, понимать и тестировать.Выше приведен первый шаг для рефакторинга: вы можете рефакторинг каждого метода в отдельный класс, реализующий интерфейс ScriptTask.

0 голосов
/ 31 декабря 2018

В программе, над которой я работаю, я достиг этого, создав конструкторы с перезаписанными методами.

public class Script 
{
    public Script()
    {

    }

    public void run()
    {

    }
}

public class TestScript extends Script
{
    public TestScript()
    {

    }

    public void run()
    {
        //This Method overwrites the run method of script. This is where your code goes.
    }
}

public class Main
{
    public static Script test = new TestScript();

    public static void main(String[] args)
    {
        test.run();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...