2017-08-18 59 views
11

Với một số Java 8 phương pháp chức năng:Cách ngắn gọn để soạn tham chiếu phương thức Java?

class Foo { Bar getBar() {} } 
class Bar { Baz getBaz() {} } 

Một thành phần của hai accessors trông giống như:

Function<Foo, Bar> getBarFromFoo = Foo::getBar; 
Function<Bar, Baz> getBazFromBar = Bar::getBaz; 
Function<Foo, Baz> getBazFromFoo = getBarFromFoo.andThen(getBazFromBar); 

Có cách nào ngắn gọn hơn? Điều này dường như hoạt động

((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz) 

Nhưng nó khá xấu xí. Các parens bên ngoài có ý nghĩa cho các lý do ưu tiên, nhưng tại sao là diễn viên cần thiết?

(Foo::getBar::getBaz sẽ được tốt đẹp, nhưng than ôi ...)

+0

Tại sao không làm 'foo -> foo.getBar() :: getBaz' ? Có vẻ như bạn đang quá phức tạp. Có cái gì tôi đang mất tích? –

+2

@VinceEmigh, ý bạn là 'foo -> foo.getBar(). GetBaz()'? nếu không, nó không có ý nghĩa – Andrew

+0

@VinceEmigh, cách bạn đề xuất không đủ linh hoạt. Tốt hơn hết là chuẩn bị những người lập bản đồ đơn giản ('a-> b',' b-> c') soạn chúng bằng các phép toán đơn giản như '' Soạn'', 'vàT' khi chạy thay vì xây dựng tất cả các trường hợp có thể tại thời gian biên dịch. – Andrew

Trả lời

3

Không có cách nào chuyên sáng tác các chức năng trong Java khác hơn andThen().

Bạn cần thực hiện dàn diễn viên vì Foo::getBar không rõ ràng. ** Nó có thể phù hợp với mọi giao diện có chữ ký phương thức tương tự.

Thật không may, ((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz) là cách tốt nhất bạn có thể làm.

10

Hãy xác định một giao diện chức năng:

@FunctionalInterface 
interface MyFunctionalInterface { 
    Bar getBar(Foo f); 
} 

Chúng ta có thể đơn giản hóa phương pháp tham khảo Foo::getBar một chút,

(Foo foo) -> foo.getBar(); 

có nghĩa "mất một Foo và trả về một Bar". Đối với mô tả rằng, rất nhiều các phương pháp phù hợp (ví dụ, giao diện của chúng tôi với getBarFuntion<Foo, Bar> với apply của nó):

MyFunctionalInterface f1 = (Foo foo) -> foo.getBar(); 
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar(); 

Đó là câu trả lời cho câu hỏi tại sao các diễn viên là cần thiết.


Để trả lời câu hỏi liệu có một cách súc tích hơn hay không, chúng tôi phải đặt ngữ cảnh. Bối cảnh rõ ràng cung cấp cho chúng tôi Function để tiếp tục làm việc với:

class Functions { 
    public static <I, O> Function<I, O> of(Function<I, O> function) { 
     return function; 
    } 
} 

Functions.of(Foo::getBar).andThen(Bar::getBaz); 
1

Có thể chỉ sử dụng biểu thức lambda?

x -> x.getBar().getBaz() 

Không có cách nào khác để soạn các chức năng khác với những gì bạn đã đề xuất vì loại mơ hồ. Số này thậm chí không dài hơn Foo::getBar::getBaz

0

Đó là điều tốt nhất bạn sẽ nhận được. Nếu bạn nghĩ rằng điều này sẽ hoạt động:

Foo::getBar::getBaz 

nó sẽ không.Đó là bởi vì Foo::getBar là một biểu thức nhiều nhiều - nó phụ thuộc vào ngữ cảnh được sử dụng - có thể là Function, nhưng cũng có thể là một ví dụ Predicate; do đó, nó có khả năng có thể áp dụng cho nhiều điều, do đó, diễn viên chỉ là cần thiết ở đó.

Bạn có thể ẩn điều đó đằng sau một phương pháp có thể thực hiện chuỗi và andThen, nhưng vấn đề vẫn còn đó.

EDIT

Xem ví dụ ở đây:

public static void cool(Predicate<Integer> predicate) { 

} 

public static void cool(Function<Integer, String> function) { 

} 

và sự biểu hiện cool(i -> "Test"); sẽ thất bại để biên dịch

+0

Cảm ơn. Tôi biết nó sẽ không hoạt động. Chỉ cần ... Loại inferencer nên biết nó không phải là một vị từ bởi vì nó không trả về boolean. Tôi không phải là trình hướng dẫn suy luận kiểu Java, nhưng có vẻ hợp lý vì Foo :: getBar thỏa mãn bất kỳ giao diện chức năng nào của biểu mẫu Foo-> Bar và getBaz thỏa mãn Bar-> Baz, thì có vẻ hợp lý là 'Foo :: getBar: : getBaz' là một biểu thức poly đáp ứng bất kỳ giao diện chức năng nào của biểu mẫu Foo-> Baz. – Gene

+0

@Gene 'Predicate' và' Function' chỉ là một ví dụ để chứng minh rằng đây thực sự là các biểu thức poly (xem sửa) ... Và 'kiểu suy luận' cho lambdas và tham chiếu phương thức không rõ ràng; đó là lý do tại sao có lẽ chuỗi này không được thực hiện ở tất cả - nó * cho đến nay * không tầm thường – Eugene

+0

Tôi đã thực sự viết một loại inferencer. Tôi biết nó không tầm thường. Điều đó không có nghĩa là không thể. – Gene

Các vấn đề liên quan