Một trường hợp sử dụng tuyệt vời là những gì tôi gọi là giao diện "đòn bẩy": các giao diện chỉ có một số ít phương thức trừu tượng (lý tưởng là 1), nhưng cung cấp rất nhiều "đòn bẩy" trong đó chúng cung cấp cho bạn rất nhiều chức năng: bạn chỉ cần triển khai 1 phương thức trong lớp của bạn nhưng nhận được rất nhiều phương thức khác "miễn phí". Hãy nghĩ về một giao diện thu thập, ví dụ, với một trừu tượng đơn foreach
phương thức và default
phương pháp thích map
, fold
, reduce
, filter
, partition
, groupBy
, sort
, sortBy
,, vv
Dưới đây là một vài ví dụ. Hãy bắt đầu với java.util.function.Function<T, R>
. Nó có một phương thức trừu tượng duy nhất R apply<T>
. Và nó có hai phương thức mặc định cho phép bạn kết hợp hàm với hàm khác theo hai cách khác nhau, trước hoặc sau. Cả hai phương thức sáng tác này đều được thực hiện bằng cách sử dụngapply
:
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
return (T t) -> after.apply(apply(t));
}
Bạn cũng có thể tạo một giao diện cho các đối tượng có thể so sánh, đại loại như thế này:
interface MyComparable<T extends MyComparable<T>> {
int compareTo(T other);
default boolean lessThanOrEqual(T other) {
return compareTo(other) <= 0;
}
default boolean lessThan(T other) {
return compareTo(other) < 0;
}
default boolean greaterThanOrEqual(T other) {
return compareTo(other) >= 0;
}
default boolean greaterThan(T other) {
return compareTo(other) > 0;
}
default boolean isBetween(T min, T max) {
return greaterThanOrEqual(min) && lessThanOrEqual(max);
}
default T clamp(T min, T max) {
if (lessThan( min)) return min;
if (greaterThan(max)) return max;
return (T)this;
}
}
class CaseInsensitiveString implements MyComparable<CaseInsensitiveString> {
CaseInsensitiveString(String s) { this.s = s; }
private String s;
@Override public int compareTo(CaseInsensitiveString other) {
return s.toLowerCase().compareTo(other.s.toLowerCase());
}
}
Hoặc một khung bộ sưu tập cực kỳ đơn giản, trong đó tất cả các hoạt động của bộ sưu tập trả về Collection
, bất kể loại ban đầu là gì:
interface MyCollection<T> {
void forEach(java.util.function.Consumer<? super T> f);
default <R> java.util.Collection<R> map(java.util.function.Function<? super T, ? extends R> f) {
java.util.Collection<R> l = new java.util.ArrayList();
forEach(el -> l.add(f.apply(el)));
return l;
}
}
class MyArray<T> implements MyCollection<T> {
private T[] array;
MyArray(T[] array) { this.array = array; }
@Override public void forEach(java.util.function.Consumer<? super T> f) {
for (T el : array) f.accept(el);
}
@Override public String toString() {
StringBuilder sb = new StringBuilder("(");
map(el -> el.toString()).forEach(s -> { sb.append(s); sb.append(", "); } );
sb.replace(sb.length() - 2, sb.length(), ")");
return sb.toString();
}
public static void main(String... args) {
MyArray<Integer> array = new MyArray<>(new Integer[] {1, 2, 3, 4});
System.out.println(array);
// (1, 2, 3, 4)
}
}
Điều này trở nên rất thú vị khi kết hợp với lambdas, bởi vì giao diện "đòn bẩy" như vậy có thể được thực hiện bởi lambda (đó là giao diện SAM).
Đây là trường hợp sử dụng tương tự như Phương thức mở rộng đã được thêm vào trong C♯, nhưng các phương thức mặc định có một ưu điểm khác biệt: chúng là các phương thức cá thể "đúng", có nghĩa là chúng có quyền truy cập vào chi tiết triển khai riêng tư của giao diện ( private
sắp có phương thức giao diện trong Java 9), trong khi Phương thức mở rộng chỉ là đường cú pháp cho phương thức tĩnh.
Nếu Java có được Giao diện tiêm, nó cũng sẽ cho phép vá khỉ kiểu mô-đun, an toàn. Điều này sẽ rất thú vị đối với những người triển khai ngôn ngữ trên JVM: hiện tại, ví dụ, JRuby hoặc thừa hưởng hoặc bọc các lớp Java để cung cấp cho họ các ngữ nghĩa bổ sung của Ruby, nhưng lý tưởng nhất là họ muốn sử dụng cùng các lớp. Với giao diện tiêm và phương pháp mặc định, họ có thể tiêm ví dụ như một RubyObject
giao diện vào java.lang.Object
, do đó một Java Object
và Ruby Object
là những điều tương tự chính xác .