Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الواجهات الوظيفية (Functional Interfaces)

جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 39 من 87.

تُعد الواجهة الوظيفية (functional interface) واجهة تحتوي على طريقة مجردة واحدة فقط. يجعل قيد الطريقة الواحدة هذا الواجهات الوظيفية مميزة لأنه يمكن تنفيذها باستخدام تعبيرات لامبدا (lambda expressions)، مما يتيح أسلوب برمجة أكثر إيجازاً.

توفر Java التعليق التوضيحي @FunctionalInterface لتمييز الواجهة صراحةً كواجهة وظيفية. على الرغم من أنه اختياري، إلا أن هذا التعليق التوضيحي يساعد المترجم (compiler) في اكتشاف الأخطاء إذا قمت بإضافة طريقة مجردة (abstract method) ثانية عن طريق الخطأ:

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

يمكنك تنفيذ واجهة وظيفية (functional interface) بالطريقة التقليدية باستخدام فئة (class)، أو بشكل أكثر إيجازاً باستخدام تعبير لامدا (lambda expression):

// التنفيذ التقليدي
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// تعبير لامدا (أقصر بكثير!)
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

لا يزال بإمكان الواجهات الوظيفية امتلاك أساليب افتراضية (default methods) وأساليب ثابتة (static methods)، حيث إنها لا تُحتسب ضمن قاعدة الأسلوب المجرد الواحد. توفر حزمة java.util.function في جافا العديد من الواجهات الوظيفية المدمجة مثل Predicate و Function و Consumer التي ستواجهها بشكل متكرر عند العمل مع التدفقات (streams) والمجموعات (collections).

challenge icon

التحدي

سهل

لنقم ببناء نظام لتحويل النصوص باستخدام الواجهات الوظيفية (functional interfaces) وتعبيرات لامبدا (lambda expressions). ستقوم بإنشاء معالج نصوص مرن يمكنه تطبيق تحويلات مختلفة على النصوص — وكل ذلك مدعوم بواجهة وظيفية واحدة.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • StringTransformer.java: قم بتعريف واجهة وظيفية تمثل أي عملية تحويل للنصوص. قم بتمييزها باستخدام التعليق التوضيحي @FunctionalInterface لضمان بقائها وظيفية. يجب أن تعلن واجهتك عن ميثود مجردة واحدة تسمى transform تأخذ String وتُرجع String.
  • TextProcessor.java: قم بإنشاء كلاس يستخدم واجهتك الوظيفية لمعالجة النصوص. يجب أن يحتوي على حقل للاحتفاظ بـ StringTransformer وكونستركتور لتهيئته. قم بتضمين ميثود تسمى process(String text) تقوم بتطبيق المحول على النص المعطى وتُرجع النتيجة. يتيح لك هذا التصميم حقن أي سلوك تحويل من خلال الكونستركتور.
  • Main.java: اجمع كل شيء معاً عن طريق إنشاء تحويلات مختلفة باستخدام تعبيرات لامبدا. ستتلقى مدخلين: سلسلة نصية ونوع العملية (upper، lower، أو reverse).

    بناءً على نوع العملية، قم بإنشاء TextProcessor باستخدام لامبدا المناسبة:

    • upper: يحول النص إلى أحرف كبيرة (uppercase)
    • lower: يحول النص إلى أحرف صغيرة (lowercase)
    • reverse: يعكس النص (تلميح: استخدم StringBuilder)

    ثم قم باستدعاء process() مع نص الإدخال واطبع النتيجة بهذا التنسيق: Result: [transformed text]

ستتلقى مدخلين: النص المراد تحويله (String) ونوع العملية (String).

لاحظ كيف يمكن لنفس الكلاس TextProcessor تنفيذ عمليات مختلفة تماماً اعتماداً على تعبير لامبدا الذي تمرره — هذه هي قوة الواجهات الوظيفية!

ورقة مرجعية

تُعد الواجهة الوظيفية (functional interface) واجهة تحتوي على طريقة مجردة واحدة فقط. ويمكن تنفيذها باستخدام تعبيرات لامبدا (lambda expressions) للحصول على كود موجز.

استخدم التعليق التوضيحي @FunctionalInterface لتمييز الواجهة كواجهة وظيفية (اختياري ولكنه موصى به):

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

يمكن تنفيذ الواجهات الوظيفية بالطريقة التقليدية أو باستخدام تعبيرات لامبدا:

// التنفيذ التقليدي
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// تعبير لامبدا
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

يمكن أن تحتوي الواجهات الوظيفية على طرق افتراضية (default) وطرق ثابتة (static) دون انتهاك قاعدة الطريقة المجردة الواحدة.

توفر حزمة java.util.function في Java واجهات وظيفية مدمجة مثل Predicate و Function و Consumer.

جرّب بنفسك

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: بناءً على نوع operation، قم بإنشاء TextProcessor باستخدام lambda المناسبة:
        // - "upper": يحول النص إلى أحرف كبيرة
        // - "lower": يحول النص إلى أحرف صغيرة
        // - "reverse": يعكس النص (تلميح: استخدم StringBuilder)
        
        // TODO: استدعِ process() مع نص الإدخال واطبع النتيجة
        // صيغة المخرجات: "Result: [transformed text]"
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming