الواجهات الوظيفية (Functional Interfaces)
جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 39 من 87.
إنَّ functional interface هي interface تحتوي على method واحدة abstract بالضبط. ويجعل هذا القيد الخاص بالـ method الواحدة من functional interfaces شيئًا مميزًا، إذ يمكن تنفيذها باستخدام تعبيرات lambda، مما يتيح أسلوبًا أكثر إيجازًا في كتابة التعليمات البرمجية.
توفر Java التعليق التوضيحي @FunctionalInterface لوضع علامة صراحةً على interface باعتبارها functional. وعلى الرغم من أن هذا التعليق التوضيحي اختياري، فإنه يساعد المترجم على اكتشاف الأخطاء إذا أضفت عن طريق الخطأ method ثانية من نوع abstract:
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}يمكنك تنفيذ functional interface بالطريقة التقليدية باستخدام class، أو بشكل أكثر إيجازًا باستخدام تعبير lambda:
// التنفيذ التقليدي
Calculator adder = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda expression (much shorter!)
Calculator adder = (a, b) -> a + b;
System.out.println(adder.calculate(5, 3)); // 8لا يزال بإمكان الواجهات الوظيفية أن تحتوي على أساليب افتراضية وأساليب ثابتة، لأن هذه الأساليب لا تُحتسب ضمن قاعدة الأسلوب المجرد الوحيد. توفّر حزمة Java java.util.function العديد من الواجهات الوظيفية المضمّنة، مثل Predicate وFunction وConsumer، وستصادفها كثيرًا عند العمل مع التدفقات والمجموعات.
التحدي
سهللنبنِ نظامًا لتحويل السلاسل النصية باستخدام functional interfaces وlambda expressions. ستنشئ معالجًا مرنًا للنصوص يمكنه تطبيق تحويلات مختلفة على السلاسل النصية: وكل ذلك مدعومًا بواجهة functional واحدة.
ستنظّم الكود عبر ثلاثة ملفات:
StringTransformer.java: Define واجهة functional تمثّل أي operation لتحويل سلسلة نصية. ميّزها بالتعليق التوضيحي@FunctionalInterfaceلضمان بقائها functional. يجب أن تعلن واجهتك عن method abstract واحدة تُسمىtransform، تأخذ String وتُعيد String.TextProcessor.java: Create class تستخدم واجهتك functional لمعالجة النص. يجب أن تحتوي على field للاحتفاظ بـStringTransformerوconstructor لتهيئته. أدرج method تُسمىprocess(String text)وتطبّق transformer على النص المحدد وتُعيد Result. يتيح لك هذا التصميم حقن أي سلوك للتحويل من خلال constructor.Main.java: اجمع كل شيء معًا من خلال إنشاء تحويلات مختلفة باستخدام lambda expressions. ستتلقى inputين: سلسلة نصية وعملية operation (upperأوlowerأوreverse).استنادًا إلى نوع operation، أنشئ
TextProcessorباستخدام lambda المناسبة:upper: تحوّل النص إلى أحرف uppercaselower: تحوّل النص إلى أحرف lowercasereverse: تعكس النص (hint: استخدمStringBuilder)
ثم استدعِ
process()باستخدام input النص واطبع Result بهذا format:Result: [transformed text]
ستتلقى inputين: النص المراد تحويله (String) ونوع operation (String).
لاحظ كيف يمكن للفئة TextProcessor نفسها تنفيذ operations مختلفة تمامًا اعتمادًا على lambda التي تمررها إليها: تلك هي قوة functional interfaces!
جرّب بنفسك
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine();
String operation = scanner.nextLine();
TextProcessor processor;
// TODO: بناءً على نوع العملية، أنشئ TextProcessor باستخدام تعبير lambda المناسب:
// - "upper": يحول النص إلى أحرف كبيرة
// - "lower": يحول النص إلى أحرف صغيرة
// - "reverse": يعكس النص (تلميح: استخدم StringBuilder)
// TODO: استدعِ process() مع النص المدخل واطبع النتيجة
// تنسيق الإخراج: "Result: [transformed text]"
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةمقدمة في الـ OOPالفئات (Classes) مقابل الكائنات (Objects)الكلمة المفتاحية thisالدوال (Methods)الحقول (Attributes)دالة البناء (Constructor)تعدد أشكال دالة البناء (Constructor Overloading)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسية (extends)الكلمة المفتاحية superإعادة تعريف الدوال (@Override)تسلسل المنشئات (Constructor Chaining)كلاس Objectالوراثة الأحادية ومتعددة المستوياتلماذا لا توجد وراثة متعددة للكلاساتمراجعة - هيكلية الموظفين7الدوال الخاصة وفئة Object
دالة toString()equals() و hashCode()دالة clone()compareTo() و Comparableواجهة Comparatorمراجعة - الترتيب المخصص2محددات الوصول والتغليف
نظرة عامة على مستويات الوصولدوال Getter و Setterإخفاء البياناتالكلمة المفتاحية finalمراجعة - مدير الحساب البنكي5تعدد الأشكال (Polymorphism)
أساسيات الـ Method Overloadingالـ Method Overriding (في وقت التشغيل)الـ Upcasting والـ Downcastingمعامل الـ instanceofالفئات والدوال المجردة (Abstract)مراجعة - حاسبة الأشكال8مفاهيم OOP المتقدمة
الـ Composition مقابل الـ Inheritanceالـ Aggregation مقابل الـ Compositionالفئات الداخلية والمتداخلة والمجهولة (Inner, Nested & Anonymous)الـ Enums ودوالهاالـ Records (Java 16+)الـ Sealed Classes (Java 17+)11أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Builderنمط Observerنمط Strategy3خصائص الفئة والعضو الساكن
المتغيرات الخاصة بالكائن مقابل المتغيرات الساكنةالدوال الساكنةالكتل البرمجية الساكنةالثوابت (static final)ملخص - العداد والأدوات المساعدة6الواجهات (Interfaces) والأصناف المجردة (Abstract Classes)
مقدمة في الواجهات (Interfaces)تنفيذ الواجهات (Interfaces)تنفيذ واجهات متعددةالـ Default و Static في الواجهاتالأصناف المجردة مقابل الواجهاتالواجهات الوظيفية (Functional Interfaces)مراجعة - نظام الدفع9الأنواع العامة (Generics)
مقدمة في الأنواع العامةالأصناف العامة (Generic Classes)الدوال العامة (Generic Methods)معاملات الأنواع المقيدةالرموز البديلة (?, extends, super)مراجعة - الحاويات العامة12أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المكررتدرّب بنفسك: مترجم Java عبر الإنترنت