freeCodeCamp/guide/arabic/java/interfaces/index.md

255 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Interfaces
localeTitle: واجهات
---
# واجهات
واجهة في جافا قليلا مثل فئة، ولكن مع فارق كبير: و `interface` يمكن أن يكون _فقط_ تواقيع طريقة والحقول والطرق الافتراضية. منذ Java 8 ، يمكنك أيضًا إنشاء [طرق افتراضية](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html) . في الجزء التالي ، يمكنك مشاهدة مثال على الواجهة:
`public interface Vehicle {
public String licensePlate = "";
public float maxVel
public void start();
public void stop();
default void blowHorn(){
System.out.println("Blowing horn");
}
}
`
تحتوي الواجهة أعلاه على حقلين وطريقتين وطريقة افتراضية. وحدها ، ليست ذات فائدة كبيرة ، ولكنها تستخدم عادة مع الفصول. ماذا؟ بسيطة ، عليك أن تتأكد من أن بعض الصف يقوم `implements` .
`public class Car implements Vehicle {
public void start() {
System.out.println("starting engine...");
}
public void stop() {
System.out.println("stopping engine...");
}
}
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CItd/0)
الآن ، هناك **قاعدة أساسية** : يجب على الفئة تنفيذ **كافة** الطرق في الواجهة. يجب أن تحتوي الطرق _على نفس_ التوقيع الضبط_ (الاسم والمعلمات والاستثناءات) كما هو موضح في الواجهة. الفئة ا_ تحتاج إلى إعلان الحقول رغم ذلك ، فقط الطرق.
## مثيلات واجهة
بمجرد إنشاء فئة Java تقوم `implements` أي واجهة ، يمكن الإشارة إلى مثيل الكائن كمثيل للواجهة. هذا المفهوم مشابه لمبدأ إنشاء الوراثة.
`// following our previous example
Vehicle tesla = new Car();
tesla.start(); // starting engine ...
`
**لا يمكن أن** تحتوي واجهة على أساليب منشئ ، لذلك **لا يمكنك** إنشاء مثيل لواجهة بنفسها. يجب إنشاء مثيل لفئة معينة تقوم بتطبيق واجهة للرجوع إليها. فكر في الواجهات على أنها نموذج عقد فارغ ، أو نموذج.
ما الذي يمكنك القيام به مع هذه الميزة؟ تعدد الأشكال! يمكنك استخدام الواجهات فقط للإشارة إلى مثيلات الكائن!
`class Truck implements Vehicle {
public void start() {
System.out.println("starting truck engine...");
}
public void stop() {
System.out.println("stopping truck engine...");
}
}
class Starter {
// static method, can be called without instantiating the class
public static void startEngine(Vehicle vehicle) {
vehicle.start();
}
}
Vehicle tesla = new Car();
Vehicle tata = new Truck();
Starter.startEngine(tesla); // starting engine ...
Starter.startEngine(tata); // starting truck engine ...
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CItm/0)
## ولكن ماذا عن واجهات متعددة؟
نعم ، يمكنك تنفيذ واجهات متعددة في فصل واحد. أثناء [تواجدك](//forum.freecodecamp.com/t/java-docs-inheritance) في [التوارث](//forum.freecodecamp.com/t/java-docs-inheritance) داخل الصفوف ، تم تقييدك في فئة واحدة فقط ، يمكنك هنا توسيع أي عدد من الواجهات. ولكن لا ننسى تنفيذ _جميع_ أساليب جميع واجهات ، وإلا سوف تفشل التجميع!
`public interface GPS {
public void getCoordinates();
}
public interface Radio {
public void startRadio();
public void stopRadio();
}
public class Smartphone implements GPS,Radio {
public void getCoordinates() {
// return some coordinates
}
public void startRadio() {
// start Radio
}
public void stopRadio() {
// stop Radio
}
}
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CIto/0)
## بعض ميزات واجهات
* يمكنك وضع المتغيرات داخل واجهة ، على الرغم من أنه لن يكون قرارًا معقولًا لأن الفئات غير مرتبطة بالمتغير نفسه. باختصار ، تجنب وضع المتغيرات!
* تكون جميع المتغيرات والطرق في الواجهة عامة ، حتى إذا تركت الكلمة الرئيسية `public` .
* لا يمكن للواجهة تحديد تنفيذ طريقة معينة. ما يصل إلى فئات للقيام بذلك. على الرغم من وجود استثناء حديث (انظر أدناه).
* إذا قامت فئة بتطبيق واجهات متعددة ، فهناك احتمال بعيد لتداخل توقيع الأسلوب. بما أن Java لا تسمح بطرق متعددة من نفس التوقيع بالضبط ، فقد يؤدي هذا إلى حدوث مشكلات. انظر [هذا السؤال](http://stackoverflow.com/questions/2598009/method-name-collision-in-interface-implementation-java) لمزيد من المعلومات.
## طرق الواجهة الافتراضية
قبل Java 8 ، لم يكن لدينا طريقة لتوجيه واجهة لتطبيق طريقة معينة. هذا يؤدي إلى الكثير من الارتباك وفواصل التعليمات البرمجية إذا تم تغيير تعريف واجهة فجأة.
لنفترض أنك كتبت مكتبة مفتوحة المصدر تحتوي على واجهة. لنفترض أن عملاءك ، أي جميع المطورين تقريبًا في جميع أنحاء العالم ، يستخدمونها بكثافة ويسعدون. الآن كان عليك ترقية المكتبة بإضافة تعريف أسلوب جديد إلى الواجهة لدعم ميزة جديدة. ولكن هذا من شأنه أن يكسر _جميع عمليات_ البناء لأن كل الطبقات التي تقوم بتنفيذ هذه الواجهة يجب أن تتغير الآن. يا لها من كارثة!
لحسن الحظ ، توفر لك Java 8 الآن الطرق `default` للواجهات. _يمكن أن_ تحتوي الطريقة `default` على التنفيذ الخاص بها _مباشرة_ داخل الواجهة! لذا ، إذا لم يقم تطبيق Class بتنفيذ طريقة افتراضية ، فسيأخذ المترجم التنفيذ المذكور داخل الواجهة. جميل أليس كذلك؟ لذلك في مكتبتك ، يمكنك إضافة أي عدد من الطرق الافتراضية في واجهات دون الخوف من كسر أي شيء!
`public interface GPS {
public void getCoordinates();
default public void getRoughCoordinates() {
// implementation to return coordinates from rough sources
// such as wifi & mobile
System.out.println("Fetching rough coordinates...");
}
}
public interface Radio {
public void startRadio();
public void stopRadio();
}
public class Smartphone implements GPS,Radio {
public void getCoordinates() {
// return some coordinates
}
public void startRadio() {
// start Radio
}
public void stopRadio() {
// stop Radio
}
// no implementation of getRoughCoordinates()
}
Smartphone motoG = new Smartphone();
motog.getRoughCoordinates(); // Fetching rough coordinates...
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CItp/0)
### ولكن ، ماذا يحدث إذا كان للواجهتين نفس توقيع الطريقة؟
سؤال رائع. في هذه الحالة ، إذا لم تقدم التطبيق في الصف ، فسوف يتم خلط المترجم الضعيف ويفشل ببساطة! يجب عليك توفير تنفيذ طريقة افتراضية داخل الفئة أيضًا. هناك أيضًا طريقة رائعة تستخدم ميزة `super` للاتصال بأي تطبيق تريده:
`public interface Radio {
// public void startRadio();
// public void stopRadio();
default public void next() {
System.out.println("Next from Radio");
}
}
public interface MusicPlayer {
// public void start();
// public void pause();
// public void stop();
default public void next() {
System.out.println("Next from MusicPlayer");
}
}
public class Smartphone implements Radio, MusicPlayer {
public void next() {
// Suppose you want to call MusicPlayer next
MusicPlayer.super.next();
}
}
Smartphone motoG = new Smartphone();
motoG.next(); // Next from MusicPlayer
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CIts/0)
## طرق ثابتة في واجهات
جديد أيضا إلى Java 8 هو القدرة على إضافة أساليب ثابتة إلى واجهات. تتشابه الطرق الثابتة في الواجهات تقريبًا مع الطرق الثابتة في الفصول الخرسانية. الاختلاف الكبير الوحيد هو أن الأساليب `static` غير موروثة في الفئات التي تقوم بتطبيق الواجهة. وهذا يعني أنه يتم الإشارة إلى الواجهة عند استدعاء الأسلوب الثابت وليس الفئة التي تقوم بتطبيقه.
`interface MusicPlayer {
public static void commercial(String sponsor) {
System.out.println("Now for a message brought to you by " + sponsor);
}
public void play();
}
class Smartphone implements MusicPlayer {
public void play() {
System.out.println("Playing from smartphone");
}
}
class Main {
public static void main(String[] args) {
Smartphone motoG = new Smartphone();
MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class
// motoG.commercial("Motorola"); // This would cause a compilation error
}
}
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CIts/9)
## وراثة واجهة
من الممكن أيضًا في Java لواجهة _ترث_ واجهة أخرى ، باستخدام ، تفكر في ذلك ، `extends` الكلمة الرئيسية:
`public interface Player {
public void start();
public void pause();
public void stop();
}
public interface MusicPlayer extends Player {
default public void next() {
System.out.println("Next from MusicPlayer");
}
}
`
هذا يعني ، أن تطبيق Class `MusicPlayer` Interface (واجهة `MusicPlayer` يجب أن يقوم بتنفيذ _جميع_ أساليب `MusicPlayer` بالإضافة إلى `Player` :
`public class SmartPhone implements MusicPlayer {
public void start() {
System.out.println("start");
}
public void stop() {
System.out.println("stop");
}
public void pause() {
System.out.println("pause");
}
}
`
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":صاروخ:") [تشغيل الكود](https://repl.it/CIty/0)
عفوًا ، هل نسيت `next()` ؟ انظر ، لأنه كان طريقة `default` ، لم يكن لدي لتوفير التنفيذ على الإطلاق. (لن يعمل لـ JDK <8)
لذلك ، الآن لديك فهم جيد للواجهات! اذهب لمعرفة المزيد عن "الطبقات المستخلصة" لتعرف كيف تقدم لك جافا طريقة أخرى لتعريف العقود.