2013-03-05 3 views
1

My collect() вызов функции Foo.f(). Я хотел бы сделать Foo.f() сам параметр моей функции. Возможно ли это на Java?Как передать функцию-член в качестве параметра в java?

  • Как я могу передать либо Foo.f() или Foo.g() (или любой другой функцией Foo, которая возвращает String) к моей функции?
  • Есть ли уже существующая функция, которая просматривает коллекцию и собирает результат вызова метода для каждого элемента коллекции?

.

class Foo { 
    public String f() { return "f"; } 
    public String g() { return "g"; } 
    // ... 
} 

public List<String> collect(List<Foo> foos) 
{ 
    List<String> result = new ArrayList<String>(); 

    for (final Foo foo: foos) { 
     result.add(foo.f()); // I want Foo.f to be a parameter 
    } 

    return result; 
} 

Update

Я хотел бы отметить тот факт, что я не просто вызывая ту же функцию, но вместо функции f члена для всех пунктов List<Foo> коллекции.

+0

Вы всегда можете использовать API отражения и передать объект Method. – duffymo

+0

Или вы можете создать интерфейс ... – pamphlet

+2

Проверьте [Command Pattern] (http://en.wikipedia.org/wiki/Command_pattern). Указатели функций не существуют в java, кроме как с отражением –

ответ

7

В Java 8, вы можете сделать

collect(foos, Foo::f); 

public List<String> collect(List<Foo> foos, Function<Foo,String> func) 
{ 
    List<String> result = new ArrayList<String>(); 

    for (final Foo foo: foos) { 
     result.add(func.apply(foo)); 
    } 

    return result; 
} 

Или с паровым API

Stream<Foo> foos = ...; 
Stream<String> strs = foos.map(Foo::f); 
+0

Java 8 еще не совсем стабилен. В более ранних версиях Java закрытие и указатели функций не поддерживаются. – RudolphEst

+0

@ RudolphEst Но если бы вы задавали этот вопрос, вы, вероятно, не собираетесь выпускать много программного обеспечения какое-то время. Возможно также использовать Java SE 8./Java SE 8 не имеет указателей на функции, а «lambdas» на самом деле больше не являются закрытием, чем анонимные внутренние классы (суть в том, что синтаксис менее подробный). –

+0

@ TomHawtin-tackline Это зависит от многого. Если ОП является студентом в университете, он может быть вынужден использовать Java 7 в своих проектах. – RudolphEst

6

Вы можете использовать интерфейсы

interface Foo 
    { 
     String fn(); 
    } 

и передать интерфейс методу

void anyMethod(Foo f) 
{ 
    f.fn(); 
} 

вам не нужно, чтобы создать бетон Foo, просто создать Foo анонимно

new Foo() { 

    @Override 
    public String fn() 
    { 
    return "something"; 
    } 
}; 

В Java 8 вам не нужно анонимно интерфейс. Вместо этого вы можете использовать выражение лямбда.

anyMethod(()-> "something"); 
+0

Я не вижу, как это решение работает с 'collect () ', поскольку я не называю просто одну и ту же функцию, а скорее той же функцией для * разных * элементов коллекции. –

+0

@MichaWiedenmann вы можете просто вызвать любой метод внутри fn() –

0

В Java вы не должны пройти метод в качестве параметра, но вы можете передать объект как параметр.

Это называется Strategy Pattern, вам нужно будет использовать интерфейс.

0

Вы можете использовать интерфейс, как:

interface IFoo { 
    String getString(); 
} 

Затем реализовать его в собственных способов:

class F implements IFoo { 
    public String getString() { 
     return "f"; 
    } 
} 

class G implements IFoo { 
    public String getString() { 
     return "g"; 
    } 
} 

И есть ваша функция принимает список всего, что реализует IFoo:

public List<String> collect(List<? extends IFoo> foos) 
{ 
    List<String> result = new ArrayList<String>(); 

    for (final IFoo foo: foos) { 
     result.add(foo.getString()); 
    } 

    return result; 
} 

Использование:

for (String a : collect(Arrays.asList(new F(), new G()))) { 
    System.out.println(a); 
} 
    //Prints f and g 
Смежные вопросы