Harika bir kullanım örneği "kaldıraç" arayüzler olarak adlandırdığım şeylerdir: sadece az sayıda soyut yönteme (ideal olarak 1) sahip olan, ancak size çok fazla işlevsellik sağladıkları için çok fazla "kaldıraç" sağlayan arayüzler: sınıfınızda 1 yöntem uygulamanız gerekir, ancak "ücretsiz" olarak başka birçok yöntem edinmeniz gerekir. Tek bir özet, örneğin bir toplama arayüzü düşünün foreach
yöntem ve default
yöntemler gibi map
, fold
, reduce
, filter
, partition
, groupBy
, sort
, sortBy
, vs.
Burada bir çift örnek var. İle başlayalım java.util.function.Function<T, R>
. Tek bir soyut yöntemi vardır R apply<T>
. Önceden veya sonra, başka bir işlevle işlevi iki farklı şekilde oluşturmanıza izin veren iki varsayılan yöntem vardır. Bu kompozisyon yöntemlerinin her ikisi de sadece kullanılarak uygulanırapply
:
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));
}
Karşılaştırılabilir nesneler için aşağıdaki gibi bir arayüz de oluşturabilirsiniz:
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());
}
}
Veya Collection
orijinal türün ne olduğuna bakılmaksızın tüm koleksiyon işlemlerinin döndüğü son derece basitleştirilmiş bir koleksiyon çerçevesi :
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)
}
}
Bu lambdalarla birlikte çok ilginç hale gelir, çünkü böyle bir "kaldıraç" arayüzü bir lambda tarafından uygulanabilir (bir SAM arayüzüdür).
Bu, Uzatma Yöntemlerinin C♯'de eklendiği kullanım örneğidir, ancak varsayılan yöntemlerin ayrı bir avantajı vardır: "uygun" örnek yöntemleridir, yani arayüzün özel uygulama ayrıntılarına erişimleri vardır ( private
arayüz yöntemleri geliyor) Java 9'da), oysa Uzatma Yöntemleri sadece statik yöntemler için sözdizimsel şekerdir.
Java hiç Arayüz Enjeksiyonu alırsa, aynı zamanda tip güvenli, kapsamlı, modüler maymun yamalamaya da izin verir. Bu, JVM'deki dil uygulayıcıları için çok ilginç olurdu: şu anda, JRuby, Java sınıflarını ek Ruby semantiği sağlamak için miras alır veya sarar, ancak ideal olarak aynı sınıfları kullanmak isterler. Yöntemler Arayüz Enjeksiyon ile ve Standart bunlar örneğin bir enjekte edebilir RubyObject
arayüz içine java.lang.Object
, yani bir Java olduğunu Object
ve Ruby Object
olan tam aynı şey .