Tôi đã sử dụng các tham chiếu lambdas và phương thức trong Java 8 một thời gian và có một điều mà tôi không hiểu. Dưới đây là mã ví dụ:Tham chiếu phương thức Java 8 và các phương thức ghi đè
Set<Integer> first = Collections.singleton(1);
Set<Integer> second = Collections.singleton(2);
Set<Integer> third = Collections.singleton(3);
Stream.of(first, second, third)
.flatMap(Collection::stream)
.map(String::valueOf)
.forEach(System.out::println);
Stream.of(first, second, third)
.flatMap(Set::stream)
.map(String::valueOf)
.forEach(System.out::println);
Hai đường ống này làm tương tự, chúng in ra ba số, một số trên mỗi dòng. Sự khác biệt nằm trong dòng thứ hai của họ, có vẻ như bạn chỉ có thể thay thế tên lớp trong phân cấp thừa kế miễn là nó có phương thức (giao diện Collection có phương thức mặc định là "stream", không được định nghĩa lại trong giao diện Set). tôi đã cố gắng ra những gì sẽ xảy ra nếu phương pháp này là xác định lại một lần nữa và một lần nữa, sử dụng các lớp:
private static class CustomHashSet<E> extends HashSet<E> {
@Override
public Stream<E> stream() {
System.out.println("Changed method!");
return StreamSupport.stream(spliterator(), false);
}
}
private static class CustomCustomHashSet<E> extends CustomHashSet<E> {
@Override
public Stream<E> stream() {
System.out.println("Changed method again!");
return StreamSupport.stream(spliterator(), false);
}
}
Sau khi thay đổi nhiệm vụ đầu tiên, thứ hai và thứ ba sử dụng các lớp này tôi có thể thay thế các tài liệu tham khảo phương pháp (CustomCustomHashSet :: suối) và không ngạc nhiên là họ đã in ra các thông báo gỡ lỗi trong mọi trường hợp, ngay cả khi tôi đã sử dụng Collection :: stream. Có vẻ như bạn không thể gọi phương thức super, overriden với các tham chiếu phương thức.
Có sự khác biệt thời gian chạy nào không? Thực hành tốt hơn là gì, hãy tham khảo giao diện/lớp cấp cao nhất hoặc sử dụng loại bê tông, loại đã biết (Set)? Cảm ơn!
Chỉnh sửa: Chỉ cần rõ ràng, tôi biết về thừa kế và LSP, sự nhầm lẫn của tôi liên quan đến thiết kế tham chiếu phương thức trong Java 8. Ý tưởng đầu tiên của tôi là thay đổi lớp trong tham chiếu phương pháp sẽ thay đổi hành vi , rằng nó sẽ gọi phương pháp siêu từ lớp được chọn, nhưng như các bài kiểm tra cho thấy, nó không có sự khác biệt. Thay đổi các kiểu cá thể đã tạo sẽ thay đổi hành vi.
Tôi luôn tưởng tượng các loại tham chiếu phương thức này (ví dụ tham chiếu tĩnh của phương thức mẫu) hoạt động giống như trong C++. Ví dụ được thêm vào như một tham số, làm một cái gì đó như 'A :: someMethod' =' (A a) -> a.someMethod() '. Bạn cũng có thể vượt qua một lớp con của A (LSP), tại đó công văn động điểm sẽ khởi động và gọi thực thi ghi đè. –
Bạn có thể đăng bài kiểm tra mà bạn đã thực hiện với 'CustomHashSet' và' CustomCustomHashSet' không? Bởi vì ngay cả khi sử dụng tham chiếu phương thức 'Collection :: stream', nếu thể hiện của đối tượng là' CustomHashSet', nó là 'CustomHashSet.stream()' sẽ được gọi ra. Bạn có chắc là bạn đã xây dựng các đối tượng 'CustomHashSet' mới? – Tunaki
@Tunaki xin lỗi nếu tôi không đủ rõ ràng. Những gì bạn mô tả là chính xác những gì đã xảy ra, nếu tôi thay đổi các trường hợp để CustomHashSet sau đó CustomHashSet.stream() đã được gọi, in "Thay đổi phương pháp!" ngay trước khi in số hiện tại. Sự nhầm lẫn của tôi là về thiết kế ngôn ngữ, suy nghĩ đầu tiên của tôi là việc thay đổi lớp trong một tham chiếu phương thức sẽ thay đổi hành vi, giống như cách bạn có thể gọi phương thức cơ sở bằng "siêu". Nhưng các bài kiểm tra cho thấy không có gì thay đổi, tất cả phụ thuộc vào loại cá thể thực tế. – Elopteryx