দুর্দান্ত ব্যবহারের ক্ষেত্রে আমি যাকে "লিভার" ইন্টারফেস বলে থাকি: ইন্টারফেসগুলিতে কেবল সংখ্যার বিমূর্ত পদ্ধতি রয়েছে (আদর্শ 1), তবে প্রচুর পরিমাণে "লিভারেজ" সরবরাহ করে যাতে তারা আপনাকে প্রচুর কার্যকারিতা সরবরাহ করে: আপনি কেবল আপনার ক্লাসে 1 টি পদ্ধতি প্রয়োগ করতে হবে তবে "বিনামূল্যে জন্য" প্রচুর অন্যান্য পদ্ধতি পান। একটি একক বিমূর্ত সঙ্গে, একটি সংগ্রহ ইন্টারফেসের চিন্তা করুন, উদাহরণস্বরূপ foreach
পদ্ধতি এবং default
পদ্ধতি পছন্দ map
, fold
, reduce
, filter
, partition
, groupBy
, sort
, sortBy
, ইত্যাদি
এখানে উদাহরণ তুলে ধরা হলো। এর সাথে শুরু করা যাক java.util.function.Function<T, R>
। এটিতে একটি একক বিমূর্ত পদ্ধতি রয়েছে R apply<T>
। এবং এর দুটি ডিফল্ট পদ্ধতি রয়েছে যা আপনাকে আগে বা পরে দুটি ভিন্ন উপায়ে ফাংশনটি রচনা করতে দেয়। এই উভয় রচনা পদ্ধতি কার্যকরভাবে ব্যবহার করে প্রয়োগ করা হয়apply
:
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));
}
আপনি তুলনামূলক অবজেক্টগুলির জন্য একটি ইন্টারফেসও তৈরি করতে পারেন, এরকম কিছু:
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());
}
}
বা একটি অতি সরলিকৃত সংগ্রহের কাঠামো, যেখানে সমস্ত সংগ্রহ অপারেশনগুলি ফিরে আসবে Collection
, আসল প্রকারটি নির্বিশেষে:
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)
}
}
ল্যাম্বডাসের সাথে এটি মিশ্রণে খুব আকর্ষণীয় হয়ে ওঠে, কারণ এই জাতীয় "লিভার" ইন্টারফেস ল্যাম্বডা দ্বারা প্রয়োগ করা যেতে পারে (এটি একটি এসএএম ইন্টারফেস)।
এটি একই ব্যবহারের ক্ষেত্রে সি'এর জন্য এক্সটেনশন পদ্ধতিগুলি যুক্ত করা হয়েছিল, তবে ডিফল্ট পদ্ধতিগুলির একটি স্বতন্ত্র সুবিধা রয়েছে: সেগুলি "যথাযথ" উদাহরণ পদ্ধতি, যার অর্থ তাদের ইন্টারফেসের ব্যক্তিগত প্রয়োগের বিশদটিতে অ্যাক্সেস রয়েছে ( private
ইন্টারফেস পদ্ধতিগুলি আসছে) জাভা 9) এ, যেখানে এক্সটেনশন পদ্ধতিগুলি কেবল স্থির পদ্ধতির জন্য সিনট্যাকটিক চিনি।
জাভা যদি কখনও ইন্টারফেস ইনজেকশন পায় তবে এটি টাইপ-সেফ, স্কোপড, মডুলার বানর-প্যাচিংয়ের অনুমতি দেবে। এটি জেভিএম-তে ভাষা প্রয়োগকারীদের জন্য অত্যন্ত আকর্ষণীয় হবে: এই মুহুর্তে, উদাহরণস্বরূপ, জে রবি হয় জাভা ক্লাস থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় বা তাদের অতিরিক্ত রুবি শব্দার্থবিজ্ঞান সরবরাহ করতে জড় করে তবে আদর্শিকভাবে তারা একই ক্লাসটি ব্যবহার করতে চায়। ইন্টারফেস ইনজেকশন পদ্ধতি এবং ডিফল্ট, তারা উদ্বুদ্ধ পারে যেমন একটি RubyObject
ইন্টারফেসে java.lang.Object
, যাতে একটি জাভা Object
এবং একটি রুবি Object
হয় সঠিক একই জিনিস ।