передача указателя на функцию методу

#function #arraylist #function-pointers #fitness

#функция #arraylist #указатели на функции #Фитнес

Вопрос:

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

Здесь код:

 class Fitness {
  private List < Double > list;
  interface Foo {
    //public Foo;
    Object myFunc(Object arg);
    Object myFunc2(Object arg);
  }
  public Fitness(List < Double > list) {
    this.list = new ArrayList < Double > (list);
  }
  public void bar(Foo foo) {
    Object object = foo.myFunc(list);
    System.out.println(object);

    Object object2 = foo.myFunc2(list);
    System.out.println(object2);
  }
  public void method(String func) {
    if (func.equals("f1"))
      bar(
        new Foo() {
          public Object myFunc(Object arg) {
            return (Double)((List) arg).get(0)   50.0;
          }
          public Object myFunc2(Object arg) {
            return (Double)((List) arg).get(0)   50.0;
          }
        });
    else if (func.equals("f2"))
      bar(
        new Foo() {
          public Object myFunc(Object arg) {
            List < Double > l = (List < Double > ) arg;
            return l.get(0) / l.size();
          }
          public Object myFunc2(Object arg) {
            List < Double > l = (List < Double > ) arg;
            return l.get(0) / l.size();
          }
        });

  }
  public void fitness1() {
    bar(
      new Foo() {
        public Object myFunc(Object arg) {
          return (Double)((List) arg).get(0)   50.0 * 1000;
        }
        public Object myFunc2(Object arg) {
          return (Double)((List) arg).get(0)   50.0;
        }
      });
  }
}

class Example {
  public static void main(String[] args) {
    ArrayList < Double > listD = new ArrayList < Double > ();
    listD.add(100.0);
    listD.add(-1.0);
    listD.add(-5.0);
    Fitness t = new Fitness(listD);
    //t.method("f1");
    //t.method("f2");
    //t.method2();
    t.fitness1();
  }
}
  

То, что я хотел бы, — это соответствие объекта, которое вызывает функцию соответствия в соответствии с некоторыми параметрами. Метод пригодности должен иметь возможность принимать список int, double, даже couple <int, String> .

Я хочу выполнить тест: поэтому я хочу увидеть разные результаты, если я выберу f1, f2, f3, f4. Я не понимаю, как это закодировать.

Заранее спасибо

Ответ №1:

Вы можете объявить следующий интерфейс:

 interface FooFunc {
    Object invoke(Foo foo, Object arg);
}
  

Затем слегка измените свой метод bar():

 public void bar(Foo foo, FooFunc func) {
    Object object = func.invoke(foo, list);
    System.out.println(object);
}
  

… и ваш метод fitness1():

 public void fitness1(FooFunc func) {
    bar(
            new Foo() {
        public Object myFunc(Object arg) {
            return (Double) ((List) arg).get(0)   50.0 * 1000;
        }

        public Object myFunc2(Object arg) {
            return (Double) ((List) arg).get(0)   50.0;
        }
    }, func);
}
  

Теперь, из вашего метода main(), вы можете сделать:

     Fitness t = new Fitness(listD);
    t.fitness1(Fitness.Foo::myFunc);
    t.fitness1(Fitness.Foo::myFunc2);
  

Разве это не здорово?

ОБНОВЛЕНИЕ: полный файл

 import java.util.ArrayList;
import java.util.List;

class Fitness {

    private List<Double> list;

    interface Foo {

        //public Foo;
        Object myFunc(Object arg);

        Object myFunc2(Object arg);
    }

    interface FooFunc {
        Object invoke(Foo foo, Object arg);
    }

    public Fitness(List<Double> list) {
        this.list = new ArrayList<Double>(list);
    }

    public void bar(Foo foo, FooFunc func) {
        Object object = func.invoke(foo, list);
        System.out.println(object);
    }

    public void fitness1(FooFunc func) {
        bar(
                new Foo() {
            public Object myFunc(Object arg) {
                return (Double) ((List) arg).get(0)   50.0 * 1000;
            }

            public Object myFunc2(Object arg) {
                return (Double) ((List) arg).get(0)   50.0;
            }
        }, func);
    }
}

public class Example {

    public static void main(String[] args) {
        ArrayList<Double> listD = new ArrayList<>();
        listD.add(100.0);
        listD.add(-1.0);
        listD.add(-5.0);
        Fitness t = new Fitness(listD);
        t.fitness1(Fitness.Foo::myFunc);
        t.fitness1(Fitness.Foo::myFunc2);
    }
}
  

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

1. Здравствуйте, я не понимаю, является ли это более ясным решением, но оно выдает мне ошибку 2 (ту же): метод bar в class Test не может быть применен к заданным типам; bar( ^ требуется: Foo,FooFunc найдено: <анонимный Foo> причина: списки фактических и формальных аргументов отличаются по длине

2. @mickey это не дает мне никакой ошибки, но дает мне 50100,0 и 150,0

3. @mickey Я не вижу ни одного вызываемого класса Test . Я добавил полный файл, который я использовал в обновлении, в свой пост.

4. Извините, я работал. Но в моем первом почтовом коде у меня было еще 2 функции «bar». Это дало мне ошибку! (функция ‘bar’s whithin’method’ …..) Любое улучшение, может быть, с помощью lambd?. Это намного сложнее, чем язык C….

5. @mickey Привет. Java — это не C. В Java нет такого понятия, как указатель на функцию; только объекты.