Given some Java 8 method functions:
给定一些Java 8方法函数:
class Foo { Bar getBar() {} }
class Bar { Baz getBaz() {} }
A composition of the two accessors looks like:
这两个访问器的组成如下:
Function<Foo, Bar> getBarFromFoo = Foo::getBar;
Function<Bar, Baz> getBazFromBar = Bar::getBaz;
Function<Foo, Baz> getBazFromFoo = getBarFromFoo.andThen(getBazFromBar);
Is there a more concise way? This seems to work
有没有更简洁的方法?这似乎工作
((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)
But it's rather ugly. The outer parens make sense for precedence reasons, but why is the cast necessary?
但它很丑。由于优先级的原因,外部参数是有意义的,但是为什么强制转换是必要的呢?
(Foo::getBar::getBaz
would be nice, but alas...)
(Foo::getBar::getBaz很好,但是唉…)
4 个解决方案
#1
10
Let's define a functional interface:
让我们定义一个功能接口:
@FunctionalInterface
interface MyFunctionalInterface {
Bar getBar(Foo f);
}
We can simplify the method reference Foo::getBar
a bit,
我们可以简化方法引用Foo::getBar一点,
(Foo foo) -> foo.getBar();
which means "take a Foo
and return a Bar
". For that description, a lot of methods are suitable (for instance, our interface with the getBar
and a Funtion<Foo, Bar>
with its apply
):
意思是“拿一个Foo然后返回一个Bar”。对于这种描述,有许多方法是合适的(例如,我们与getBar的接口和函数
MyFunctionalInterface f1 = (Foo foo) -> foo.getBar();
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar();
That is the answer to the question why the cast is necessary.
这就是为什么演员是必须的问题的答案。
To answer the question whether there is a more concise way affirmatively, we have to set a context. The context unambiguously gives us a Function
to continue working with:
要确定是否有更简洁的方式,我们必须建立一个背景。上下文明确地给了我们一个继续工作的函数:
class Functions {
public static <I, O> Function<I, O> of(Function<I, O> function) {
return function;
}
}
Functions.of(Foo::getBar).andThen(Bar::getBaz);
#2
3
There is no dedicated way of composing functions in Java other than andThen()
.
除了andThen()之外,Java中没有专门的函数组合方式。
You need to perform the cast because Foo::getBar
is ambiguous. **It could match every interface having similar method signature.
您需要执行cast,因为Foo::getBar是不明确的。**它可以匹配每个具有相似方法签名的接口。
Unfortunately, ((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)
is the best you can do.
然后(Bar::getBaz)是你能做的最好的事情。
#3
1
Maybe just use a lambda expression?
也许只用一个lambda表达式?
x -> x.getBar().getBaz()
There is no other way to compose functions other than what you already suggested because of type ambiguity. This is not even much longer than Foo::getBar::getBaz
由于类型歧义,除了您已经建议的方法之外,没有其他方法组合函数。这甚至比Foo::getBar: getBaz长不了多少
#4
0
That's the best you are going to get. If you think that this would work:
这是你能得到的最好的结果。如果你认为这行得通:
Foo::getBar::getBaz
it will not. That's because Foo::getBar
is a poly expression - it depends on the context used - it could be a Function
, but could also be a Predicate
for example; so it could potentially apply to many things, so the cast is just necessary there.
它不会。这是因为Foo: getBar是一个poly表达式——它取决于所使用的上下文——它可以是一个函数,也可以是一个谓词,例如;所以它可能适用于很多东西,所以石膏只是必要的。
You could hide that behind a method that would do the chaining and andThen
, but the problem is still there.
你可以把它隐藏在一个方法后面,然后进行链接,但是问题仍然存在。
EDIT
编辑
See an example here:
看一个例子:
public static void cool(Predicate<Integer> predicate) {
}
public static void cool(Function<Integer, String> function) {
}
and the expression cool(i -> "Test");
will fail to compile
和表示cool(i ->“Test”);将无法编译
#1
10
Let's define a functional interface:
让我们定义一个功能接口:
@FunctionalInterface
interface MyFunctionalInterface {
Bar getBar(Foo f);
}
We can simplify the method reference Foo::getBar
a bit,
我们可以简化方法引用Foo::getBar一点,
(Foo foo) -> foo.getBar();
which means "take a Foo
and return a Bar
". For that description, a lot of methods are suitable (for instance, our interface with the getBar
and a Funtion<Foo, Bar>
with its apply
):
意思是“拿一个Foo然后返回一个Bar”。对于这种描述,有许多方法是合适的(例如,我们与getBar的接口和函数
MyFunctionalInterface f1 = (Foo foo) -> foo.getBar();
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar();
That is the answer to the question why the cast is necessary.
这就是为什么演员是必须的问题的答案。
To answer the question whether there is a more concise way affirmatively, we have to set a context. The context unambiguously gives us a Function
to continue working with:
要确定是否有更简洁的方式,我们必须建立一个背景。上下文明确地给了我们一个继续工作的函数:
class Functions {
public static <I, O> Function<I, O> of(Function<I, O> function) {
return function;
}
}
Functions.of(Foo::getBar).andThen(Bar::getBaz);
#2
3
There is no dedicated way of composing functions in Java other than andThen()
.
除了andThen()之外,Java中没有专门的函数组合方式。
You need to perform the cast because Foo::getBar
is ambiguous. **It could match every interface having similar method signature.
您需要执行cast,因为Foo::getBar是不明确的。**它可以匹配每个具有相似方法签名的接口。
Unfortunately, ((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)
is the best you can do.
然后(Bar::getBaz)是你能做的最好的事情。
#3
1
Maybe just use a lambda expression?
也许只用一个lambda表达式?
x -> x.getBar().getBaz()
There is no other way to compose functions other than what you already suggested because of type ambiguity. This is not even much longer than Foo::getBar::getBaz
由于类型歧义,除了您已经建议的方法之外,没有其他方法组合函数。这甚至比Foo::getBar: getBaz长不了多少
#4
0
That's the best you are going to get. If you think that this would work:
这是你能得到的最好的结果。如果你认为这行得通:
Foo::getBar::getBaz
it will not. That's because Foo::getBar
is a poly expression - it depends on the context used - it could be a Function
, but could also be a Predicate
for example; so it could potentially apply to many things, so the cast is just necessary there.
它不会。这是因为Foo: getBar是一个poly表达式——它取决于所使用的上下文——它可以是一个函数,也可以是一个谓词,例如;所以它可能适用于很多东西,所以石膏只是必要的。
You could hide that behind a method that would do the chaining and andThen
, but the problem is still there.
你可以把它隐藏在一个方法后面,然后进行链接,但是问题仍然存在。
EDIT
编辑
See an example here:
看一个例子:
public static void cool(Predicate<Integer> predicate) {
}
public static void cool(Function<Integer, String> function) {
}
and the expression cool(i -> "Test");
will fail to compile
和表示cool(i ->“Test”);将无法编译