الواجهات و Lambda
الواجهات (Interfaces) تحدد عقدًا (contract) تلتزم به الفئات. في هذا الدرس، سنتعلم كيفية استخدام الواجهات.
تعريف الواجهة
JAVA
public interface Drawable {
void draw(); // دالة مجردة
void setColor(String color); // دالة مجردة
}
تنفيذ الواجهة
JAVA
public class Circle implements Drawable {
private String color;
@Override
public void draw() {
System.out.println("رسم دائرة");
}
@Override
public void setColor(String color) {
this.color = color;
System.out.println("اللون: " + color);
}
}
public class Rectangle implements Drawable {
private String color;
@Override
public void draw() {
System.out.println("رسم مستطيل");
}
@Override
public void setColor(String color) {
this.color = color;
System.out.println("اللون: " + color);
}
}
الواجهات مع تعدد الأشكال
JAVA
Drawable[] shapes = {new Circle(), new Rectangle()};
for (Drawable shape : shapes) {
shape.setColor("أحمر");
shape.draw();
}
تنفيذ عدة واجهات
JAVA
public interface Printable {
void print();
}
public interface Serializable {
void save();
}
public class Document implements Printable, Serializable {
@Override
public void print() {
System.out.println("طباعة المستند");
}
@Override
public void save() {
System.out.println("حفظ المستند");
}
}
الدوال الافتراضية (Java 8+)
JAVA
public interface Logger {
void log(String message);
// دالة افتراضية
default void logError(String message) {
log("خطأ: " + message);
}
// دالة ثابتة
static Logger createConsoleLogger() {
return message -> System.out.println("[LOG] " + message);
}
}
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("[FILE] " + message);
}
}
// الاستخدام
Logger logger = new FileLogger();
logger.log("رسالة"); // [FILE] رسالة
logger.logError("خطأ"); // [FILE] خطأ: خطأ
Logger console = Logger.createConsoleLogger();
console.log("رسالة"); // [LOG] رسالة
الواجهات الوظيفية (Functional Interfaces)
واجهة وظيفية هي واجهة تحتوي على دالة مجردة واحدة فقط:
JAVA
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}
// استخدام Lambda
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
Calculator multiply = (a, b) -> a * b;
System.out.println(add.calculate(5, 3)); // 8
System.out.println(subtract.calculate(5, 3)); // 2
System.out.println(multiply.calculate(5, 3)); // 15
الواجهات المدمجة
Comparable — للمقارنة
JAVA
public class Student implements Comparable<Student> {
private String name;
private double gpa;
public Student(String name, double gpa) {
this.name = name;
this.gpa = gpa;
}
@Override
public int compareTo(Student other) {
return Double.compare(this.gpa, other.gpa);
}
}
// استخدام
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("أحمد", 3.5));
students.add(new Student("محمد", 3.8));
students.add(new Student("علي", 3.2));
Collections.sort(students); // ترتيب حسب GPA
Runnable — للخيوط
JAVA
public class MyTask implements Runnable {
@Override
public void run() {
System.out.println("المهمة تعمل في خيط: " + Thread.currentThread().getName());
}
}
// استخدام
Thread thread = new Thread(new MyTask());
thread.start();
// بـ Lambda
Thread thread2 = new Thread(() -> {
System.out.println("Lambda تعمل في خيط");
});
thread2.start();
❓ أسئلة شائعة
س ما الفرق بين الواجهة والفئة المجردة؟
ج الواجهة: عقد بحت (دوال مجردة فقط). الفئة المجردة: يمكن أن تحتوي على كود عادي.
س لماذا نستخدم @FunctionalInterface؟
ج للتحقق من أن الواجهة تحتوي على دالة مجردة واحدة فقط.
س هل يمكن أن تحتوي الواجهة على متغيرات؟
ج المتغيرات في الواجهة تكون public static final (ثوابت).
📖 ملخص
- الواجهة تحدد عقدًا تلتزم به الفئات
- implements لتنفيذ الواجهة
- يمكن تنفيذ عدة واجهات
- default و static للدوال الافتراضية والثابتة
- @FunctionalInterface للواجهات الوظيفية
📝 تمارين
- أشكال: أنشئ واجهة Shape مع دوال للمساحة والمحيط
- وظائف: أنشئ واجهة Payable مع دالة calculatePay
- Lambda: استخدم Lambda لترتيب ArrayList
الدرس التالي
في الدرس التالي، سنتعلم Enums والفئات الداخلية — الأنواع المخصصة والفئات المتداخلة.



