English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تعليميات Java الأساسية

Java Flow Control

Java Arrays

Java Object-Oriented (I)

Java Object-Oriented (II)

Java Object-Oriented (III)

معالجة الاستثنائات في Java

Java List

Java Queue (Queue)

Java Map Collections

Java Set Collections

Java Input/Output (I/O)

Java Reader/Writer

مواضيع أخرى في Java

الواجهات في Java (Interface)

في هذا الدرس، سنتعلم عن واجهات Java. سنتعلم من خلال الأمثلة كيفية تنفيذ الواجهة و متى يجب استخدامها.

في Java، تعرف الواجهة مجموعة من المعايير التي يجب تنفيذها من قبل الفئات الأخرى. على سبيل المثال،

interface Polygon {
   public void getArea();
{}

هنا Polygon هي واجهة. نستخدم كلمة المفتاح interface لتحديد واجهة.

طريقة getArea() هي معيار معرف في واجهة Polygon. يجب على جميع الفئات التي تستخدم هذه الواجهة تنفيذ طريقة getArea().

يمكن للواجهة أن تحتوي على طرق تجريبية ومتغيرات ثابتة. على سبيل المثال،

interface Polygon {
   public static final String color = "blue";
   
   public void getArea();
{}

في هذا المثال، قمنا بإنشاء واجهة Polygon. إنها تحتوي على متغير ثابت color وطرق تجريبية getArea().

من المهم ملاحظة أن جميع الطرق في الواجهة هي public بشكل تلقائي، وكل الحقول هي public static final. لذلك، لا تحتاج إلى تحديد واضع الوصول داخل الواجهة. على سبيل المثال، يمكننا كتابة الكود كالتالي

interface Polygon {
   String color = "blue";
   
    void getArea();
{}

كلمة المفتاح interface و implements

مثل الفئة التجريبية، لا يمكننا إنشاء عناصر واجهة. ولكن يمكننا تنفيذ الواجهة في فئات أخرى. في Java، نستخدم كلمة المفتاح implements لتنفيذ الواجهة. على سبيل المثال،

interface Polygon {
    void getArea(int طول, int عرض);
{}
class Rectangle implements Polygon {
    public void getArea(int طول, int عرض) {
        System.out.println("مساحة المربع هي " + (طول * عرض));
    {}
{}
class Main {
    public static void main(String[] args) {
        Rectangle r1 = new Rectangle();
        r1.getArea(5, 6);
    {}
{}

نتائج الإخراج

مساحة المربع هو 30

في البرنامج السابق، قمنا بإنشاء واجهة Polygon. واجهة Polygon تحتوي على طريقة مضمونة抽象ة getArea().

 يعني أن أي فئة تنفذ Polygon يجب أن تقدم تنفيذًا للطريقة getArea().

لاحظ أن فئة Rectangle (تنفذ واجهة Polygon) تحتوي على طريقة محلية مضمونة getArea().

لماذا نستخدم الواجهات؟

الآن بعد أن عرفنا ما هو الواجهة، دعنا نعرف لماذا يتم استخدام الواجهات في Java.

  • تقدم الواجهات معايير يجب أن تتبعها الفئات (تنفيذها).

  • في المثال السابق، قمنا باستخدام getArea() كمعيار في واجهة Polygon. هذا يشبه إعداد قاعدة، يجب أن نتمكن من الحصول على مساحة كل مضلع. لذلك، يجب أن يقدم أي فئة تتمكن من تنفيذ واجهة Polygon تنفيذًا لطريقة getArea().

  • مثل الفئات التجريبية، يمكن للواجهات مساعدتنا في تحقيق التجريد في Java. هنا، نعلم أن getArea() يحسب مساحة المضلع، ولكن لكل مضلع طريقة مختلفة لتحديد المساحة. لذلك، تنفصل تنفيذات getArea().

  • تستخدم الواجهات أيضًا لتوليد التوليد المتعدد في Java. إذا كانت الفئة تنشأ من اثنين أو أكثر من الفئات، فإنها هي توليد متعدد.

    في Java، لا يمكن الوصول إلى التوليد المتعدد من خلال النسخة الممتدة. ولكن يمكن للفئة تنفيذ عدة واجهات. هذا يمكن أن يعطينا وظيفة التوليد المتعدد في Java. على سبيل المثال،

    واجهة Line {
       ...
    {}
    interface Polygon {
       ...
    {}
    class Rectangle implements Line, Polygon{
       ...
    {}

    في هذا السياق، يجب على Rectangle تقديم تنفيذ لجميع الطرق في Line و Polygon.

طرق الخاصة و الثابتة في الواجهة

في Java 8، يمكن للواجهات الآن أن تحتوي على طرق ثابتة.

مثل الكلاسات، يمكننا استخدام مرجع لاستدعاء الطرق الثابتة في الواجهة. على سبيل المثال،

Polygon.staticMethod();

إلى جانب ذلك، تدعم واجهات إصدار Java 9 الطرق الخاصة. الآن يمكنك استخدامالطريقة الخاصةوالطريقة الثابتة الخاصة.

بما أن الواجهة لا يمكن إنشاؤها، يتم استخدام الطرق الخاصة كطرق مساعدة لتقديم دعم للطرق الأخرى في الواجهة.

طرق افتراضية في الواجهة

في Java 8، تم إدخال طرق محلية مضمونة (طرق افتراضية) داخل واجهات، و قبل ذلك كانت جميع الطرق هي طرق مضمونة في Java.

في داخل واجهة يجب علينا استخدام كلمة المفتاح default لتحديد طريقة افتراضية. على سبيل المثال،

public default void getSides() {
   // جسم getSides()
{}

لماذا استخدام الطريقة الافتراضية؟

دعونا نستخدم سيناريو لفهم لماذا تم تقديم الطريقة الافتراضية في Java.

افترض أننا نحتاج إلى إضافة طريقة جديدة في الوجهة.

يمكننا بسهولة إضافة هذا الطريقة في الوجهة دون تنفيذ. ولكن، هذا ليس نهاية القصة. جميع الكلاسات التي نقوم بتنفيذ هذه الوجهة يجب أن تقدم تنفيذ لهذه الطريقة.

إذا كان هناك العديد من الكلاسات يحققون هذا الوجهة، فإننا بحاجة إلى تتبع جميع هذه الكلاسات وتغييرها. هذا ليس فقط مزعجًا، بل من المحتمل أن يحدث فيه خطأ.

لحل هذه المشكلة، قدم Java الطريقة الافتراضية. الطريقة الافتراضية تورث مثل الطريقة العادية.

دعونا نستخدم مثالاً لفهم الطريقة الافتراضية بشكل أفضل.

مثال 2: الطريقة الافتراضية

interface Polygon {
   void getArea();
   default void getSides() {
      System.out.println("أستطيع الحصول على جوانب المضلع.");
   {}
{}
class Rectangle implements Polygon {
   public void getArea() {
      int length = 6;
      int breadth = 5;
      int area = length * breadth;
      System.out.println("مساحة المربع هو " + area);
   {}
   public void getSides() {
      System.out.println("لدي أربعة جوانب.");
   {}
{}
class Square implements Polygon {
   public void getArea() {
      int length = 5;
      int area = length * length;
      System.out.println("مساحة المربع هي " + area);
   {}
{}
class Main {
   public static void main(String[] args) {
      Rectangle r1 = new Rectangle();
      r1.getArea();
      r1.getSides();
      Square s1 = new Square();
      s1.getArea();
   {}
{}

نتائج الإخراج

مساحة المربع هو 30
لدي أربعة جوانب.
مساحة المربع هي 25

في المثال السابق، قمنا بإنشاء واجهة Polygon. Polygon لديها طريقة افتراضية getSides() و طريقة ربط抽象ة getArea().

ثم، كلاس Rectangle يحقق Polygon، Rectangle يقدم تنفيذ طريقة الربط getArea() ويغطي الطريقة الافتراضية getSides().

نا创建了另一个Square كلاس، هو أيضًا يحقق Polygon. في هذا المكان، Square يقدم فقط تنفيذ طريقة الربط getArea().

مثال تطبيقي حقيقي للواجهة

دعونا نرى مثالاً عملياً أكثر للواجهة Java.

// استخدام دالة sqrt
import java.lang.Math;
interface Polygon {
   void getArea();
  
     // حساب طول المضلع
   default void getPerimeter(int... sides) {
      int perimeter = 0;
      for (int side : sides) {
         perimeter += side;
      {}
   System.out.println("طول: " + perimeter);
   {}
{}
class Triangle implements Polygon {
   private int a, b, c;
   private double s, area;
    // تعيين جوانب المثلث
   Triangle(int a, int b, int c) {
      this.a = a;
      this.b = b;
      this.c = c;
      s = 0;
   {}
    // حساب مساحة المثلث
   public void getArea() {
      s = (double) (a + b + c) / 2;
      area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
      System.out.println("المساحة: " + area);
   {}
{}
class Main {
   public static void main(String[] args) {
      Triangle t1 = new Triangle(2, 3, 4);
      // دعوة طريقة Triangle
      t1.getArea();
      // دعوة طريقة Polygon
      t1.getPerimeter(2, 3, 4);
   {}
{}

نتائج الإخراج

المساحة: 2.9047375096555625
طول: 9

في البرنامج أعلاه، قمنا بإنشاء واجهة Polygon. إنها تشمل الطريقة الافتراضية getParameter() والطريقة التجريبية getArea().

يمكننا حساب طول جميع المضلعات بنفس الطريقة، لذا قمنا بإنشاء جسم getPerimeter() في Polygon. الآن، يمكن لجميع المضلعات التي تحقق Polygon استخدام getPerimeter() لحساب الطول.

لكن طريقة حساب المساحة تختلف باختلاف الشكل المثلثي، لأن قواعد حساب المساحة تختلف باختلاف الشكل المثلثي.

لذلك، لم يتم تنفيذ getArea() في Polygon لكن تم تشغيلها. وكل فئة تنفذ واجهة Polygon يجب أن تقدم تنفيذًا لـ getArea().

واجهة باستخدام مفتاح الكلمة extends

مثل الفئات، يمكن للواجهة أن تورث واجهات أخرى، ويستخدم مفتاح الكلمة extends للوراثة. على سبيل المثال،

واجهة Line {
   // أعضاء واجهة Line
{}
واجهة Polygon تمتد Line {
   // أعضاء واجهة Polygon وواجهة Line
{}

في المثال السابق، تمتد واجهة Polygon بواجهة Line. الآن، إذا كان هناك فئة تنفذ Polygon، فإنها يجب أن تقدم تنفيذًا لكل كلاس抽象 في Line و Polygon.

الاحتياط، يمكن للواجهة أن تورث واجهات متعددة، مثل فئة تنفذ عدة واجهات.

واجهة A {
   ...
{}
واجهة B {
   ... 
{}
واجهة C تمتد A, B {
   ...
{}