Java 8 đã thêm khái niệm về các giao diện chức năng , cũng như nhiều phương thức mới được thiết kế để có các giao diện chức năng. Thể hiện của các giao diện này có thể được tạo ra một cách ngắn gọn bằng cách sử dụng các biểu thức tham chiếu phương thức (ví dụ SomeClass::someMethod
) và biểu thức lambda (ví dụ (x, y) -> x + y
).
Một đồng nghiệp và tôi có ý kiến khác nhau về việc tốt nhất nên sử dụng hình thức này hay hình thức khác (trong đó "tốt nhất" trong trường hợp này thực sự sôi sục đến "dễ đọc nhất" và "phù hợp nhất với thông lệ tiêu chuẩn", vì về cơ bản chúng là khác tương đương). Cụ thể, điều này liên quan đến trường hợp sau đây đều đúng:
- chức năng trong câu hỏi không được sử dụng bên ngoài một phạm vi
- đặt tên cá thể giúp dễ đọc (trái ngược với logic là đủ đơn giản để xem nhanh những gì đang diễn ra)
- không có lý do lập trình nào khác tại sao một hình thức lại thích hợp hơn hình thức kia.
Ý kiến hiện tại của tôi về vấn đề này là việc thêm một phương thức riêng tư và tham khảo rằng bằng cách tham chiếu phương thức, là cách tiếp cận tốt hơn. Cảm giác như đây là cách tính năng được thiết kế để sử dụng và có vẻ dễ dàng hơn để truyền đạt những gì đang diễn ra thông qua tên phương thức và chữ ký (ví dụ: "boolean isResultInFuture (Kết quả kết quả)" rõ ràng đang nói rằng nó sẽ trả về một boolean). Nó cũng làm cho phương thức riêng có thể tái sử dụng nhiều hơn nếu một lớp nâng cao trong tương lai muốn sử dụng cùng một kiểm tra, nhưng không cần trình bao bọc giao diện chức năng.
Sở thích của đồng nghiệp của tôi là có một phương thức trả về thể hiện của giao diện (ví dụ: "Dự đoán kết quảInFuture ()"). Đối với tôi, cảm giác này không hoàn toàn giống như cách sử dụng tính năng này, cảm giác hơi cục mịch và dường như khó thực hiện hơn ý định truyền đạt thông qua việc đặt tên.
Để làm cho ví dụ này cụ thể, đây là cùng một mã, được viết theo các kiểu khác nhau:
public class ResultProcessor {
public void doSomethingImportant(List<Result> results) {
results.filter(this::isResultInFuture).forEach({ result ->
// Do something important with each future result line
});
}
private boolean isResultInFuture(Result result) {
someOtherService.getResultDateFromDatabase(result).after(new Date());
}
}
so với
public class ResultProcessor {
public void doSomethingImportant(List<Result> results) {
results.filter(resultInFuture()).forEach({ result ->
// Do something important with each future result line
});
}
private Predicate<Result> resultInFuture() {
return result -> someOtherService.getResultDateFromDatabase(result).after(new Date());
}
}
so với
public class ResultProcessor {
public void doSomethingImportant(List<Result> results) {
Predicate<Result> resultInFuture = result -> someOtherService.getResultDateFromDatabase(result).after(new Date());
results.filter(resultInFuture).forEach({ result ->
// Do something important with each future result line
});
}
}
Có bất kỳ tài liệu hoặc nhận xét chính thức hoặc bán chính thức nào xung quanh việc một phương pháp được ưu tiên hơn, phù hợp hơn với ý định của nhà thiết kế ngôn ngữ hay dễ đọc hơn không? Chặn một nguồn chính thức, có bất kỳ lý do rõ ràng tại sao một trong những cách tiếp cận tốt hơn?
Object::toString
). Vì vậy, câu hỏi của tôi là nhiều hơn về việc liệu nó tốt hơn trong trường hợp cụ thể mà tôi đặt ra ở đây, hơn là liệu có tồn tại trường hợp nào tốt hơn trường hợp khác hay ngược lại.