الواجهات الوظيفية المخصصة
تعريف واجهتكم الخاصة باستخدام @FunctionalInterface
الواجهات الوظيفية المخصصة درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
ما الذي يجعل الواجهة وظيفية
تحتوي الواجهة الوظيفية على دالة مجردة واحدة بالضبط (SAM). وهذه الدالة الوحيدة هي ما ينفّذه تعبير lambda.
- لا تُحتسب الدوال الافتراضية والساكنة ضمن الحد.
interface Greeter {
String greet(String name);
}
public class Main {
public static void main(String[] args) {
Greeter g = name -> "Hello, " + name;
System.out.println(g.greet("Ada"));
}
}التعليق التوضيحي @FunctionalInterface
يطلب @FunctionalInterface من المُصرّف فرض قاعدة الدالة المجردة الوحيدة. وإذا أضفتم دالة مجردة ثانية عن طريق الخطأ، فسيفشل التصريف.
@FunctionalInterface
interface Calculator {
int compute(int a, int b);
}
public class Main {
public static void main(String[] args) {
Calculator add = (a, b) -> a + b;
System.out.println(add.compute(3, 4));
}
}لماذا يفيد التعليق التوضيحي
يوثّق التعليق التوضيحي القصد ويحمي العقد. وبدونه تظل الواجهة صالحة كواجهة وظيفية، لكن يمكن لزميل في الفريق إفسادها بإضافة دالة مجردة أخرى.
@FunctionalInterface
interface Transformer {
String apply(String input);
}
public class Main {
public static void main(String[] args) {
Transformer reverse = s -> new StringBuilder(s).reverse().toString();
System.out.println(reverse.apply("abc"));
}
}واجهة مخصّصة باستخدام الأنواع العامة
يمكن أن تكون واجهتكم عامة، مثل الواجهات المضمّنة.
@FunctionalInterface
interface Converter<S, T> {
T convert(S source);
}
public class Main {
public static void main(String[] args) {
Converter<String, Integer> toInt = Integer::parseInt;
System.out.println(toInt.convert("123") + 1);
}
}السماح بالدوال الافتراضية
يمكن أن تحتوي الواجهة الوظيفية على دوال default. فهي تضيف سلوكًا من دون الإخلال بقاعدة الدالة المجردة الوحيدة.
@FunctionalInterface
interface Operation {
int apply(int x);
default Operation then(Operation next) {
return x -> next.apply(this.apply(x));
}
}
public class Main {
public static void main(String[] args) {
Operation inc = x -> x + 1;
Operation dbl = x -> x * 2;
System.out.println(inc.then(dbl).apply(5));
}
}السماح بالدوال الساكنة أيضًا
يمكن أن تعمل الدوال الساكنة كمصانع، على غرار Function.identity().
@FunctionalInterface
interface Mapper {
int map(int x);
static Mapper identity() {
return x -> x;
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Mapper.identity().map(99));
}
}طرح الاستثناءات المفحوصة
إذا أعلنت دالتكم المجردة عن استثناء مفحوص، فيمكن لتعبير lambda طرحه. ولا يمكن لـ Function المضمّنة فعل ذلك، وهذا أحد أسباب تعريف واجهتكم الخاصة.
@FunctionalInterface
interface RiskyParser {
int parse(String s) throws NumberFormatException;
}
public class Main {
public static void main(String[] args) {
RiskyParser p = Integer::parseInt;
System.out.println(p.parse("77"));
}
}تمرير الواجهات المخصّصة إلى الدوال
تصبح واجهتكم نوعًا لمعامل، مما يتيح للمتصلين تزويد السلوك باستخدام تعبيرات lambda.
@FunctionalInterface
interface IntCombiner {
int combine(int a, int b);
}
public class Main {
static int reduce(int[] arr, IntCombiner c) {
int acc = arr[0];
for (int i = 1; i < arr.length; i++) acc = c.combine(acc, arr[i]);
return acc;
}
public static void main(String[] args) {
int[] data = {1, 2, 3, 4};
System.out.println(reduce(data, (a, b) -> a + b));
}
}واجهة بثلاثة معاملات
توفّر JDK واجهات لمعامل واحد ولمعاملين فقط. أما عند الحاجة إلى ثلاثة معاملات أو أكثر، فعليكم تعريف واجهتكم الخاصة.
@FunctionalInterface
interface TriFunction<A, B, C, R> {
R apply(A a, B b, C c);
}
public class Main {
public static void main(String[] args) {
TriFunction<Integer, Integer, Integer, Integer> sum3 = (a, b, c) -> a + b + c;
System.out.println(sum3.apply(1, 2, 3));
}
}تناسب مراجع الدوال الواجهات المخصّصة
يمكن توفير أي دالة يطابق توقيعها توقيع SAM باستخدام مرجع دالة.
@FunctionalInterface
interface StringTest {
boolean check(String s);
}
public class Main {
public static void main(String[] args) {
StringTest blank = String::isBlank;
System.out.println(blank.check(" "));
}
}الفئة المجهولة مقابل lambda
يُعد تعبير lambda بديلًا مختصرًا عن فئة مجهولة تنفّذ واجهة وظيفية. وينتج كلاهما السلوك نفسه.
@FunctionalInterface
interface Action {
void run();
}
public class Main {
public static void main(String[] args) {
Action old = new Action() {
public void run() { System.out.println("anonymous"); }
};
Action neo = () -> System.out.println("lambda");
old.run();
neo.run();
}
}تحقّق سريع
ما الذي يضمنه @FunctionalInterface؟
مراجعة
لقد عرّفتم واجهاتكم الوظيفية الخاصة:
- تحتوي الواجهة الوظيفية على دالة مجردة واحدة بالضبط (SAM).
- يفرض
@FunctionalInterfaceهذه القاعدة في وقت التصريف. - يُسمح بالدوال الافتراضية والساكنة، والأنواع العامة، والاستثناءات المفحوصة.
- تسد الواجهات المخصّصة الفجوات التي لا تغطيها JDK، مثل الدوال ذات ثلاثة معاملات أو تعبيرات lambda التي تطرح استثناءات مفحوصة.
الأسئلة الشائعة
هل درس «الواجهات الوظيفية المخصصة» مجاني؟
نعم — نص درس «الواجهات الوظيفية المخصصة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «الواجهات الوظيفية المخصصة»؟
تعريف واجهتكم الخاصة باستخدام @FunctionalInterface تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «الواجهات الوظيفية المخصصة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- Function وBiFunction
- Supplier وConsumer
- Predicate والتركيب
- الواجهات الوظيفية المخصصة