JavaRush /جاوا بلاگ /Random-SD /جاوا ۾ فنڪشنل انٽرفيس

جاوا ۾ فنڪشنل انٽرفيس

گروپ ۾ شايع ٿيل
سلام! Java Syntax Pro جستجو ۾، اسان لامبڊا ايڪسپريسز جو اڀياس ڪيو ۽ چيو ته اھي ھڪ فنڪشنل انٽرفيس مان ھڪ فنڪشنل طريقي تي عمل ڪرڻ کان وڌيڪ ڪجھ به نه آھن. ٻين لفظن ۾، اهو ڪجهه گمنام (نامعلوم) طبقي جو عمل آهي، ان جو غير حقيقي طريقو. ۽ جيڪڏهن ڪورس جي ليڪچرن ۾ اسان لامبڊا جي اظهارن سان ٺاهه ڪرڻ ۾ مشغول ٿي چڪا آهيون، هاڻي اسان غور ڪنداسين، تنهنڪري ڳالهائڻ لاء، ٻئي طرف: يعني، اهي تمام انٽرنيٽ. جاوا جي اٺين ورزن ۾ فنڪشنل انٽرفيسجاوا ۾ فنڪشنل انٽرفيس - 1 جو تصور متعارف ڪرايو . هي ڇا آهي؟ ھڪڙو انٽرفيس ھڪڙي غير لاڳو ٿيل (خلاصي) طريقي سان ڪم ڪري ٿو. ڪيتريون ئي ٻاهريون انٽرفيس هن تعريف هيٺ اچي وڃن ٿا، جهڙوڪ، مثال طور، اڳ ۾ بحث ڪيل انٽرفيس . ۽ پڻ انٽرفيس جيڪي اسان پاڻ ٺاهيندا آهيون، جهڙوڪ: Comparator
@FunctionalInterface
public interface Converter<T, N> {
   N convert(T t);
}
اسان وٽ هڪ انٽرفيس آهي جنهن جو ڪم هڪ قسم جي شين کي ٻئي جي شين ۾ تبديل ڪرڻ آهي (هڪ قسم جو اڊاپٽر). تشريح @FunctionalInterfaceڪا وڏي پيچيده يا اهم نه آهي، ڇاڪاڻ ته ان جو مقصد اهو آهي ته مرتب ڪندڙ کي ٻڌايو ته هي انٽرفيس ڪم ڪندڙ آهي ۽ ان ۾ هڪ کان وڌيڪ طريقو نه هجڻ گهرجي. جيڪڏهن هن تشريح سان گڏ هڪ انٽرفيس هڪ کان وڌيڪ غير لاڳو ٿيل (خلاصو) طريقو آهي، مرتب ڪندڙ هن انٽرفيس کي نه ڇڏيندو، ڇاڪاڻ ته اهو ان کي غلط ڪوڊ سمجهي سگهندو. هن تشريح کان سواء انٽرفيس فنڪشنل سمجهي سگهجي ٿو ۽ ڪم ڪندو، پر @FunctionalInterfaceاهو اضافي انشورنس کان وڌيڪ ڪجهه ناهي. اچو ته واپس ڪلاس ڏانهن وڃو Comparator. جيڪڏھن توھان ان جو ڪوڊ ڏسو (يا دستاويز )، توھان ڏسي سگھوٿا ته ان ۾ ھڪڙي کان وڌيڪ طريقا آھن. پوء توهان پڇو: ڪيئن، پوء، ان کي هڪ فنڪشنل انٽرفيس سمجهي سگهجي ٿو؟ خلاصو انٽرفيس جا طريقا ٿي سگھن ٿا جيڪي ھڪڙي طريقي جي دائري ۾ نه آھن:
  • جامد
انٽرفيس جي تصور جو مطلب اهو آهي ته ڪوڊ جو هڪ ڏنل يونٽ ڪنهن به طريقن تي عمل نه ٿو ڪري سگهي. پر جاوا 8 سان شروع ڪندي، انٽرفيس ۾ جامد ۽ ڊفالٽ طريقا استعمال ڪرڻ ممڪن ٿيو. جامد طريقا سڌو سنئون طبقي سان جڙيل آهن ۽ اهڙي طريقي کي سڏڻ لاءِ ان طبقي جي ڪنهن خاص شئي جي ضرورت نه آهي. اهو آهي، اهي طريقا مناسب طور تي انٽرفيس جي تصور ۾ مناسب آهن. مثال طور، اچو ته هڪ جامد طريقو شامل ڪريون ڪنهن شئي کي چيڪ ڪرڻ لاءِ پوئين ڪلاس ۾ null لاءِ:
@FunctionalInterface
public interface Converter<T, N> {

   N convert(T t);

   static <T> boolean isNotNull(T t){
       return t != null;
   }
}
اهو طريقو حاصل ڪرڻ کان پوء، مرتب ڪندڙ شڪايت نه ڪئي، جنهن جو مطلب آهي ته اسان جو انٽرفيس اڃا تائين ڪم ڪري رهيو آهي.
  • ڊفالٽ طريقا
جاوا 8 کان اڳ، جيڪڏهن اسان کي انٽرفيس ۾ هڪ طريقو ٺاهڻ جي ضرورت آهي جيڪا ٻين طبقن کان وراثت ۾ هئي، اسان صرف هڪ خلاصو طريقو ٺاهي سگهون ٿا جيڪو هر مخصوص طبقي ۾ لاڳو ڪيو ويو هو. پر ڇا جيڪڏهن اهو طريقو سڀني طبقن لاء ساڳيو آهي؟ هن حالت ۾ ، تجريدي طبقن کي اڪثر استعمال ڪيو ويو . پر جاوا 8 سان شروع ڪندي، اتي هڪ اختيار آهي انٽرفيس استعمال ڪرڻ لاءِ لاڳو ٿيل طريقن سان - ڊفالٽ طريقا. جڏهن هڪ انٽرفيس کي ورثي ۾ ملي، توهان انهن طريقن کي ختم ڪري سگهو ٿا يا هر شيء کي ڇڏي ڏيو (ڊفالٽ منطق کي ڇڏي ڏيو). جڏهن هڪ ڊفالٽ طريقو ٺاهيو، اسان کي لفظ شامل ڪرڻ گهرجي - default:
@FunctionalInterface
public interface Converter<T, N> {

   N convert(T t);

   static <T> boolean isNotNull(T t){
       return t != null;
   }

   default void writeToConsole(T t) {
       System.out.println("Текущий an object - " + t.toString());
   }
}
ٻيهر، اسان ڏسون ٿا ته مرتب ڪندڙ شڪايت ڪرڻ شروع نه ڪيو، ۽ اسان فنڪشنل انٽرفيس جي حدن کان ٻاهر نه وڃو.
  • اعتراض طبقي جا طريقا
ليڪچر Comparing Objects ۾ ، اسان ان حقيقت جي باري ۾ ڳالهايو ته سڀئي طبقا ڪلاس مان ورثي ۾ ملن ٿا Object. اهو انٽرفيس تي لاڳو نٿو ٿئي. پر جيڪڏهن اسان وٽ انٽرفيس ۾ هڪ خلاصو طريقو آهي جيڪو دستخط سان ملندو آهي طبقي جي ڪنهن طريقي سان Object، اهڙو طريقو (يا طريقا) اسان جي فنڪشنل انٽرفيس جي پابندي کي ٽوڙي نه سگهندو:
@FunctionalInterface
public interface Converter<T, N> {

   N convert(T t);

   static <T> boolean isNotNull(T t){
       return t != null;
   }

   default void writeToConsole(T t) {
       System.out.println("Текущий an object - " + t.toString());
   }

   boolean equals(Object obj);
}
۽ ٻيهر، اسان جو مرتب ڪندڙ شڪايت نه ڪندو آهي، تنهنڪري انٽرفيس Converterاڃا تائين فنڪشنل سمجهيو ويندو آهي. هاڻي سوال اهو آهي ته: اسان کي هڪ فنڪشنل انٽرفيس ۾ هڪ غير لاڳو ٿيل طريقي سان پاڻ کي محدود ڪرڻ جي ضرورت آهي؟ ۽ پوء انهي ڪري ته اسان ان کي استعمال ڪري سگھون ٿا lambdas. اچو ته ان کي هڪ مثال سان ڏسو Converter. هن کي ڪرڻ لاء، اچو ته هڪ ڪلاس ٺاهيو Dog:
public class Dog {
  String name;
  int age;
  int weight;

  public Dog(final String name, final int age, final int weight) {
     this.name = name;
     this.age = age;
     this.weight = weight;
  }
}
۽ هڪ جهڙو Raccoon(ريڪون):
public class Raccoon {
  String name;
  int age;
  int weight;

  public Raccoon(final String name, final int age, final int weight) {
     this.name = name;
     this.age = age;
     this.weight = weight;
  }
}
فرض ڪريو اسان وٽ هڪ اعتراض آهي Dog، ۽ اسان کي ان جي فيلڊ جي بنياد تي هڪ اعتراض ٺاهڻ جي ضرورت آهي Raccoon. اھو آھي، Converterاھو ھڪڙي قسم جي ھڪڙي شيء کي ٻئي ۾ تبديل ڪري ٿو. اهو ڪيئن نظر ايندو:
public static void main(String[] args) {
  Dog dog = new Dog("Bobbie", 5, 3);

  Converter<Dog, Raccoon> converter = x -> new Raccoon(x.name, x.age, x.weight);

  Raccoon raccoon = converter.convert(dog);

  System.out.println("Raccoon has parameters: name - " + raccoon.name + ", age - " + raccoon.age + ", weight - " + raccoon.weight);
}
جڏهن اسان ان کي هلائيندا آهيون، اسان ڪنسول ڏانهن هيٺين آئوٽ حاصل ڪندا آهيون:

Raccoon has parameters: name - Bobbbie, age - 5, weight - 3
۽ هن جو مطلب آهي ته اسان جو طريقو صحيح ڪم ڪيو.جاوا ۾ فنڪشنل انٽرفيس - 2

بنيادي جاوا 8 فنڪشنل انٽرفيس

خير، هاڻي اچو ته ڪيترن ئي فنڪشنل انٽرفيس تي نظر رکون جيڪي جاوا 8 اسان کي کڻي آيا آهن ۽ جيڪي فعال طور تي استعمال ڪيا ويا آهن اسٽريم API سان گڏ.

اڳڪٿي ڪرڻ

Predicate- هڪ فنڪشنل انٽرفيس چيڪ ڪرڻ لاءِ ته ڇا هڪ خاص شرط ملي ٿي. جيڪڏهن شرط پورا ٿي وڃي، واپسي true، ٻي صورت ۾ - false:
@FunctionalInterface
public interface Predicate<T> {
   boolean test(T t);
}
مثال طور، ھڪڙو ٺاھڻ تي غور ڪريو Predicateجيڪو ھڪڙي قسم جي برابري جي جانچ ڪندو Integer:
public static void main(String[] args) {
   Predicate<Integer> isEvenNumber = x -> x % 2==0;

   System.out.println(isEvenNumber.test(4));
   System.out.println(isEvenNumber.test(3));
}
ڪنسول آئوٽ:

true
false

ڪنڀار

Consumer(انگريزي کان - "صارف") - هڪ فنڪشنل انٽرفيس جيڪو T قسم جي اعتراض کي ان پٽ دليل طور وٺندو آهي، ڪجهه ڪارناما انجام ڏئي ٿو، پر ڪجھ به نه موٽائي ٿو:
@FunctionalInterface
public interface Consumer<T> {
   void accept(T t);
}
مثال جي طور تي، غور ڪريو ، جنهن جو ڪم اهو آهي ته ڪنسول ڏانهن هڪ سلام پيش ڪرڻ سان منظور ٿيل اسٽرنگ دليل سان: Consumer
public static void main(String[] args) {
   Consumer<String> greetings = x -> System.out.println("Hello " + x + " !!!");
   greetings.accept("Elena");
}
ڪنسول آئوٽ:

Hello Elena !!!

فراهم ڪندڙ

Supplier(انگريزي - فراهم ڪندڙ کان) - هڪ فنڪشنل انٽرفيس جيڪو ڪو به دليل نٿو وٺي، پر T قسم جو اعتراض واپس ڪري ٿو:
@FunctionalInterface
public interface Supplier<T> {
   T get();
}
مثال طور، غور ڪريو Supplier، جيڪو ھڪڙي فهرست مان بي ترتيب نالا پيدا ڪندو:
public static void main(String[] args) {
   ArrayList<String> nameList = new ArrayList<>();
   nameList .add("Elena");
   nameList .add("John");
   nameList .add("Alex");
   nameList .add("Jim");
   nameList .add("Sara");

   Supplier<String> randomName = () -> {
       int value = (int)(Math.random() * nameList.size());
       return nameList.get(value);
   };

   System.out.println(randomName.get());
}
۽ جيڪڏهن اسان هن کي هلائيندا آهيون، اسان ڏسنداسين بي ترتيب نتيجا ڪنسول ۾ نالن جي فهرست مان.

فنڪشن

Function- هي فنڪشنل انٽرفيس هڪ دليل T وٺندو آهي ۽ ان کي قسم R جي اعتراض ڏانهن وڌائيندو آهي، جنهن جي نتيجي ۾ موٽايو ويندو آهي:
@FunctionalInterface
public interface Function<T, R> {
   R apply(T t);
}
مثال طور، اچو ته وٺون ، جيڪو انگن کي اسٽرنگ فارميٽ ( ) مان نمبر فارميٽ ( ): FunctionStringInteger
public static void main(String[] args) {
   Function<String, Integer> valueConverter = x -> Integer.valueOf(x);
   System.out.println(valueConverter.apply("678"));
}
جڏهن اسان ان کي هلائيندا آهيون، اسان ڪنسول ڏانهن هيٺين آئوٽ حاصل ڪندا آهيون:

678
PS: جيڪڏهن اسان نه رڳو انگ، پر ٻيا اکر پڻ اسٽرنگ ۾ داخل ڪريون ٿا، هڪ استثنا اڇلايو ويندو - NumberFormatException.

يونيري آپريٽر

UnaryOperator- ھڪڙو فنڪشنل انٽرفيس جيڪو ھڪڙي قسم جي ھڪڙي شيء کي پيراميٽر جي طور تي وٺي ٿو، ان تي ڪجھ آپريشن انجام ڏئي ٿو ۽ ساڳي قسم جي T جي ھڪڙي اعتراض جي صورت ۾ عملن جو نتيجو واپس ڪري ٿو:
@FunctionalInterface
public interface UnaryOperator<T> {
   T apply(T t);
}
UnaryOperator، جيڪو applyهڪ نمبر چورس ڪرڻ لاءِ ان جو طريقو استعمال ڪري ٿو:
public static void main(String[] args) {
   UnaryOperator<Integer> squareValue = x -> x * x;
   System.out.println(squareValue.apply(9));
}
ڪنسول آئوٽ:

81
اسان پنج فنڪشنل انٽرفيس کي ڏٺو. اهو سڀ ڪجهه نه آهي جيڪو اسان وٽ موجود آهي جاوا 8 سان شروع ڪندي - اهي مکيه انٽرفيس آهن. باقي موجود آهن انهن جا پيچيده اينالاگ آهن. مڪمل فهرست سرڪاري Oracle دستاويزن ۾ ڳولهي سگھجي ٿو .

اسٽريم ۾ فنڪشنل انٽرفيس

جيئن مٿي بحث ڪيو ويو آهي، اهي فنڪشنل انٽرفيس مضبوط طور تي اسٽريم API سان گڏ آهن. ڪيئن، توهان پڇو؟ جاوا ۾ فنڪشنل انٽرفيس - 3۽ جيئن ته ڪيترائي طريقا Streamخاص طور تي انهن فنڪشنل انٽرفيس سان ڪم ڪن ٿا. اچو ته ڏسو ته ڪيئن فنڪشنل انٽرفيس استعمال ڪري سگھجن ٿيون Stream.

Predicate سان طريقو

مثال طور، اچو ته طبقي جو طريقو وٺون Stream- filterجيڪو هڪ دليل جي طور تي وٺندو آهي Predicate۽ Streamصرف اهي عنصر واپس آڻيندو آهي جيڪي شرط کي پورو ڪن ٿا Predicate. جي حوالي سان Stream-a، هن جو مطلب اهو آهي ته اهو صرف انهن عناصرن مان گذري ٿو جيڪي واپس ايندا آهن trueجڏهن توهان انهن کي testانٽرفيس طريقي سان استعمال ڪندا آهيو Predicate. اھو اھو آھي جيڪو اسان جو مثال جھڙو نظر ايندو Predicate، پر عنصرن جي فلٽر لاءِ Stream:
public static void main(String[] args) {
   List<Integer> evenNumbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8)
           .filter(x -> x % 2==0)
           .collect(Collectors.toList());
}
نتيجي طور، فهرست evenNumbersعناصر تي مشتمل هوندي {2, 4, 6, 8}. ۽، جيئن اسان کي ياد آهي، collectاهو سڀني عناصر کي هڪ خاص مجموعي ۾ گڏ ڪندو: اسان جي صورت ۾، ۾ List.

صارفين سان گڏ طريقو

طريقن مان هڪ آهي Stream، جيڪو فنڪشنل انٽرفيس استعمال ڪري ٿو Consumer، اهو آهي peek. اھو اھو آھي جيڪو اسان جي مثال Consumer۾ نظر ايندو Stream:
public static void main(String[] args) {
   List<String> peopleGreetings = Stream.of("Elena", "John", "Alex", "Jim", "Sara")
           .peek(x -> System.out.println("Hello " + x + " !!!"))
           .collect(Collectors.toList());
}
ڪنسول آئوٽ:

Hello Elena !!!
Hello John !!!
Hello Alex !!!
Hello Jim !!!
Hello Sara !!!
پر جيئن ته طريقو peekڪم ڪري ٿو Consumer، ان ۾ تارن جي ترميم Streamنه ٿيندي، پر اصل عنصرن سان peekواپس ايندي Stream: ساڳيءَ طرح جيئن اهي آيون. تنهن ڪري، فهرست peopleGreetings"ايلينا"، "جان"، "ايلڪس"، "جم"، "سارا" عناصر تي مشتمل هوندي. اتي پڻ ھڪڙو عام استعمال ٿيل طريقو آھي foreach، جيڪو طريقو سان ملندڙ جلندڙ آھي peek، پر فرق اھو آھي ته اھو حتمي آھي.

فراهم ڪندڙ سان طريقو

ھڪڙي طريقي جو ھڪڙو مثال Streamجيڪو استعمال ڪري ٿو فنڪشنل انٽرفيس Supplierآھي generate، جيڪو ان کي منظور ٿيل فنڪشنل انٽرفيس جي بنياد تي لامحدود تسلسل ٺاھي ٿو. اچو ته اسان جو مثال استعمال ڪريون Supplierڪنسول ۾ پنج بي ترتيب نالن کي پرنٽ ڪرڻ لاءِ:
public static void main(String[] args) {
   ArrayList<String> nameList = new ArrayList<>();
   nameList.add("Elena");
   nameList.add("John");
   nameList.add("Alex");
   nameList.add("Jim");
   nameList.add("Sara");

   Stream.generate(() -> {
       int value = (int) (Math.random() * nameList.size());
       return nameList.get(value);
   }).limit(5).forEach(System.out::println);
}
۽ اھو اھو آھي جيڪو اسان حاصل ڪندا آھيون ڪنسول ۾:

John
Elena
Elena
Elena
Jim
ھتي اسان استعمال ڪيو طريقو limit(5)تي حد مقرر ڪرڻ لاءِ generate، ٻي صورت ۾ پروگرام بي ترتيب نالن کي ڪنسول تي اڻڄاڻ طور پرنٽ ڪندو.

فنڪشن سان طريقو

Streamدليل سان گڏ ھڪڙي طريقي جو ھڪڙو عام مثال Functionھڪڙو طريقو آھي mapجيڪو ھڪڙي قسم جي عناصر کي وٺي ٿو، انھن سان ڪجھھ ڪري ٿو ۽ انھن کي منتقل ڪري ٿو، پر اھي اڳ ۾ ئي مختلف قسم جا عنصر ٿي سگھن ٿا. Functionان ۾ ڪهڙو مثال نظر اچي سگهي ٿو Stream:
public static void main(String[] args) {
   List<Integer> values = Stream.of("32", "43", "74", "54", "3")
           .map(x -> Integer.valueOf(x)).collect(Collectors.toList());
}
نتيجي طور، اسان کي انگن جي هڪ فهرست ملي ٿي، پر Integer.

UnaryOperator سان طريقو

هڪ طريقي جي طور تي جيڪو UnaryOperatorهڪ دليل طور استعمال ڪري ٿو، اچو ته هڪ طبقي جو طريقو وٺو Stream- iterate. هي طريقو ان طريقي سان ملندڙ جلندڙ آهي generate: اهو پڻ هڪ لامحدود تسلسل ٺاهي ٿو پر ٻه دليل آهن:
  • پهريون اهو عنصر آهي جنهن مان تسلسل نسل شروع ٿئي ٿو.
  • ٻيو آهي UnaryOperator، جيڪو پهريون عنصر مان نوان عنصر پيدا ڪرڻ جي اصول کي ظاهر ڪري ٿو.
اھو اھو آھي جيڪو اسان جو مثال جھڙو نظر ايندو UnaryOperator، پر طريقي سان iterate:
public static void main(String[] args) {
   Stream.iterate(9, x -> x * x)
           .limit(4)
           .forEach(System.out::println);
}
جڏهن اسان ان کي هلائيندا آهيون، اسان ڪنسول ڏانهن هيٺين آئوٽ حاصل ڪندا آهيون:

9
81
6561
43046721
اهو آهي، اسان جو هر عنصر پاڻ ۾ ضرب ڪيو ويندو آهي، ۽ ائين ئي پهرين چئن انگن لاء. جاوا ۾ فنڪشنل انٽرفيس - 4اهو ئي سڀ ڪجهه آهي! اهو تمام سٺو ٿيندو جيڪڏهن هن آرٽيڪل پڙهڻ کان پوءِ توهان جاوا ۾ اسٽريم API کي سمجهڻ ۽ ماهر ڪرڻ جي هڪ قدم ويجهو آهيو!
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION