It's kinda hard to explain the problem so I will explain with the code below.
I would like to create the method applyAll.
applyAll take a setter method from the User class and call a function (passed as parameter) to set value of that method.
Problems are:
- what is the type of User::setLogin ?
- how can I call this generic method ?
public class UserBuilder {
private List<User> users;
/* ... */
public <T> UserBuilder applyAll(??? method, Function<Integer, T> func) {
for (int index = 0; index < users.size(); index ) {
// I don't know how to call 'method' parameter (which is a method of User class)
users.get(i)[method](func.apply(index));
}
return this;
}
public UserBuilder withLogin(Function<Integer, String> func) {
return applyAll(User::setLogin, func);
}
/* ... */
}
public class User {
private String login;
void setLogin(String login) { this.login = login; }
}
Example of use case:
List<User> users = new UserBuilder(10).withLogin((index) -> "user_" index).build();
CodePudding user response:
In this case, User::setLogin
can resolve into a java.util.function.BiConsumer<User, T>
:
public <T> UserBuilder applyAll(BiConsumer<User, T> setter, Function<Integer, T> func) {
for (int i = 0; i < users.size(); i ) {
setter.accept(users.get(i), func.apply(i));
}
return this;
}
CodePudding user response:
The setter that is relevant here must clearly 'take' one parameter, of type T
(after all, that's what you pass to it in your example code - the result of func.apply(index)
, which is an instance of T), and which returns - well, nothing. It's a setter.
Thus, it's a java.util.function.Consumer<T>
- a method that takes Ts and produces nothing - that 'consumes Ts'. To be perfectly correct, it'd be allright if the setter consumes some supertype of Ts just as well (if your function produces Integers, and your setter accepts Numbers - that's okay). So let's make that Consumer<? super T>
.
public <T> UserBuilder applyAll(Consumer<? super T> setter, Function<Integer, T> func) {
...
}
and you can call it:
List<String> names = ....;
Function<Integer, String> nameMaker = idx -> names.get(idx);
builder.applyAll(User::setName, nameMaker);