
لدي أسئلة حول تعبيرات لامدا و RxJava. تتعلق هذه الأسئلة في الغالب بفهم غير كامل لتعابير لامدا أو RxJava. سأحاول أن أشرح عبارات لامدا بسيطة بقدر الإمكان. RxJava سأصف بشكل منفصل.
تعابير لامدا و RxJava
ما هي تعابير لامدا؟ تعد تعبيرات Lambda "مجرد" طريقة جديدة للقيام بنفس الشيء الذي يمكننا القيام به دائمًا ، ولكن بطريقة جديدة أكثر نظافة وأقل تفصيلاً لاستخدام الطبقات الداخلية المجهولة.
فئة داخلية مجهولة في Java هي فئة غير مسماة ، يجب استخدامها إذا كنت بحاجة إلى تجاوز أساليب الطبقة أو الواجهة. يمكن إنشاء فئة داخلية مجهولة من فئة أو واجهة.
على سبيل المثال:
abstract class Animal { abstract void speak(); } Animal a = new Animal() { void speak() { System.out.println("Woff"); } }; 
في Android ، نستخدم عادةً فئة داخلية مجهولة كمستمع ، على سبيل المثال ، للأزرار من هذا النوع:
 Button btn = findViewById(R.id.button); btn.setOnClickListener( new View.OnClickListener() { @Override public void onClick(final View view) {  
دعنا نعود إلى تعابير لامدا. هذا هو الجزء التالي ، وهو جزء من الرمز السابق ، والذي يعتبر فئة داخلية مجهولة.
 new View.OnClickListener() { @Override public void onClick(final View view) {  
يمكن استخدام تعبيرات Lambda فقط إذا كنت بحاجة إلى تجاوز طريقة واحدة على الأكثر. لحسن الحظ بالنسبة لنا ، تحتوي View.OnClickListener على واحدة فقط. ألق نظرة على الرمز أدناه. أي جزء تعتقد أنه علينا إزالته؟
 new View.OnClickListener() { @Override public void onClick(final View view) {  
بعد إزالة جميع التعليمات البرمجية تقريبًا ، نحتاج إلى إضافة -> ، كما في الرمز أدناه. يمكن استخدام عرض معلمة الإدخال داخل الوظيفة بنفس الطريقة السابقة.
 (view) -> {  
في بعض الحالات ، قد تحتاج إلى إضافة نوع إلى معلمة ، إذا لم يتمكن المترجم من تخمينه ، يمكنك القيام بذلك عن طريق إضافته قبل المعلمة:
 (View view) -> {  
يمكنك أيضًا استخدام رمز متعدد الأسطر:
 (view) -> { Intent intent = new Intent(context, AuthActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); view.getContext().startActivity(intent); } 
إذا كان لديك واجهة مع طريقة تأخذ معلمتين ...
 interface MyInterface { abstract void onMethod(int a, int b); } 
... سيبدو تعبير لامدا كما يلي:
 (a, b) -> {  
إذا كان للطريقة نوع إرجاع ...
 interface MySecondInterface { abstract int onSecondMethod(int a, int b); } 
... سيبدو تعبير لامدا كما يلي:
 (a, b) -> { return a + b; } 
ولكن هذا ليس كل شيء ، فهناك بعض الحالات الخاصة التي تجعل الشفرة أصغر. إذا كان نص الطريقة يحتوي على سطر واحد فقط من التعليمات البرمجية ، فيمكنك إزالة الأقواس المتعرجة {} . إذا قمت بإزالة الأقواس المتعرجة ، فستحتاج أيضًا إلى إزالة الفاصلة المنقوطة ، مع ترك ما يلي:
 (a, b) -> return a + b 
هناك شيء آخر يمكننا القيام به. إذا كان لدينا سطر واحد فقط من التعليمات البرمجية ، فيمكن للمترجم أن يفهم ما إذا كان الجزء الذي تم إرجاعه مطلوبًا أم لا ، لذا يمكننا تركه على النحو التالي:
 (a, b) -> a + b 
إذا كان لدينا رمز متعدد الأسطر ، فسوف ينزل إلى ما يلي:
 (a, b) -> { a+=1; return a + b; } 
إذن ماذا فعلنا؟ أخذنا هذا:
 new MySecondInterface() { @Override public int onSecondMethod(final int a, final int b) { return a + b; } }; 
وحولته إلى هذا:
 (a, b) -> a + b 
لم يبق سوى شيء واحد ، مراجع الطريقة. لنفترض أن لدينا واجهة ، كما كان من قبل ، وطريقة تقبل هذه الواجهة كمعلمة:
 public interface Callback { public void onEvent(int event); } public void myMethod(Callback callback){ } 
بدون تعبير لامدا ، ستبدو كما يلي:
 myMethod(new Callback() { @Override public void onEvent(final int state) { System.out.println(state); } }); 
بإضافة تعبير لامدا ، كما فعلنا من قبل ، نحصل على ما يلي:
 myMethod(state -> System.out.println(state)); 
لكن هذا ليس كل شيء إذا كان الكود المستخدم عبارة عن سطر واحد وكانت الوظيفة المطلوبة تأخذ معلمة واحدة ، فيمكننا تمرير مرجع الطريقة في هذا النموذج:
 myMethod(System.out::println); 
سيتم تمرير المعلمة تلقائيًا ، دون الحاجة إلى رمز آخر! حق مدهش؟ أتمنى أن تكون قد تعلمت شيئًا جديدًا!