-2

I'm trying to create a list of suppliers. I have ClassA with instance methods getOne(), getTwo(). Then In ClassB, I have a method to return a list of suppliers as below:

public List<Supplier<String>> getData(){
    return Arrays.asList(
        ClassA::getOne,
        ClassA::getTwo
    );
}

I can't make the methods static. I actually need to call getData() from other class. This other class don't know what method from which class to invoke. It just call the getData() from an abstract class (in this case ClassA extends some abstract class) and iterate the list and call those methods. So this other class can call getData() from any instance of the abstract class

iPhoneJavaDev
  • 821
  • 5
  • 33
  • 78
  • 2
    You can't call an instance method without an instance. – shmosel Aug 02 '18 at 02:02
  • or maybe make the method static - without seeing your code I have no idea if you can or not – Scary Wombat Aug 02 '18 at 02:04
  • 1
    Also `ClassA::getOne` does not look like a method call – Scary Wombat Aug 02 '18 at 02:05
  • I can't make the methods static. I actually need to call getData() from other class. This other class don't know what method from which class to invoke. It just call the getData() from an abstract class (in this case ClassA extends some abstract class) and iterate the list and call those methods. So this other class can call getData() from any instance of the abstract class. – iPhoneJavaDev Aug 02 '18 at 02:06
  • 2
    If the caller has an instance of `ClassA`, change the return type to `Function` and it'll work fine. – shmosel Aug 02 '18 at 02:10
  • @shmosel It's clear to me that that is what OP wants. Perhaps you could post it as an answer? I can promise you an upvote. I think you'd need to mention that the class that calls all of this will need to call the `apply` method on everything in the list. – Dawood ibn Kareem Aug 02 '18 at 02:21
  • This may be an A-B-problem (with a better solution not using Suppliers if you give more context). For example, dependency injection is a common approach to when a piece of code needs to get something but does not know how to obtain it. – Thilo Aug 02 '18 at 02:35

1 Answers1

7

Assuming the caller class has an instance of ClassA and you want to specify which methods to call, you'll need to use a Function that accepts the instance and returns the result of the method call. In other words, you'll need to change the return type to List<Function<ClassA, String>>. The method body can remain the same. To invoke the functions, you'll need to call apply(), e.g.:

ClassA instance = ...
for (Function<ClassA, String> method : getData()) {
    String result = method.apply(instance);
    System.out.println(result);
}

Alternatively, as pointed out by @Thilo, you can have the method accept an instance and return a list of suppliers that invoke a method on the provided instance:

public List<Supplier<String>> getData(ClassA instance) {
    return Arrays.asList(
        instance::getOne,
        instance::getTwo
    );
}
shmosel
  • 49,289
  • 6
  • 73
  • 138
  • 4
    The other alternative (if one really needs to return a list of Suppliers) would be that `getData` takes the `instance` as a parameter and captures it locally. The returned suppliers would then "remember" it. Either way, someone has to provide the instance. – Thilo Aug 02 '18 at 02:33