Search code examples
javafunctional-interface

Pass lambda (Object -> Object) to function in Java


what type to use, when i wish to pass a lambda to a function, with lambda accepting and returning an object?

Example of the use can be seen below. I wanna be able to create instances of Foo, where each instance can is able to, in this example, call a prespeficied getter function.

class Foo() {
public ? lambdaFunction;

public Object doSomething(Object arbitraryClass);
    return lambdaFunction(arbitraryClass);
}

foo.lambdaFunction = (Object object) -> ((SomeClass) object).getAttribite())
foo.doSomething(someClassInstance);

I have a large number of classes with number of getable attributes, and need to be able to get all of those attributes at different places, but the only thing that changes is the actually classes getter name.


Solution

  • class Foo {
        private final Function<Object, ?> func;
    
        public Foo(Function<Object, ?> func) {
            this.func = func;
        }
    
        public Object doSomething(Object in) {
            return func.apply(in);
        }
    }
    

    But I doubt you actually want that. Java is a nominally typed language - you're supposed to use names, and lots of them. 'Object' doesn't mean much. For example, given that the function needs to be able to convert any object, the function you pass in can't do anything with that object (well, other than toString, hashCode, and the other methods all objects have). The function could cast the input, but that's ugly.

    This sounds like a better plan already:

    class Foo<F, T> {
        private final Function<? super F, ? extends T> func;
    
        public Foo(Function<? super F, ? extends T> func) {
            this.func = func;
        }
    
        public T doSomething(F in) {
            return func.apply(in);
        }
    }
    

    F and T are short for 'from' and 'to'. The reason it's ? super F is because if you are looking to convert, say, strings to integers, and you have a function that convert any object to an integer, that's good too: You want it to convert either String, or any supertype thereof, and for the 'to', any subtype is also fine.


    Extending this answer in light of your recent comments:

    Java isn't dynamically typing. No random mysterymeat grabbags of functions that may or may not even make sense given the provided input. Thus, if you want a 'function that describes a setter, e.g. that takes 2 input arguments', then that's a completely different concept: That'd be a function that requires a Receiver and a new Value to set, and returns nothing. 2 inputs, 0 outputs. j.u.f.Function is 1 input, 1 output.

    2 inputs, 0 outputs would be java.util.function.BiConsumer<T, U>. Look at the java.util.function API for these types.

    class Example {
        private String name;
    
        public void setName(String name) { this.name = name; }
        public String getName() { return name; }
    
        public static final BiConsumer<Example, String> SETTER = Example::setName;
    }
    
    class SomeplaceElse {
        void foo() {
            Example e = new Example();
            String n = "hello";
            Example.SETTER.accept(e, n);
            System.out.println(e.getName()); // prints 'hello'
        }
    }