في Java، يمكن أن تحتوي بعض الفئات على فئات أخرى بداخلها. تسمى هذه الفئات بالفئات المتداخلة. تنقسم الفئات المحددة ضمن فئات أخرى بشكل عام إلى فئتين - ثابتة وغير ثابتة. تسمى الفئات غير الثابتة المتداخلة بالداخلية. تسمى الفئات المتداخلة التي تم تعريفها بأنها ثابتة فئات متداخلة ثابتة. في الواقع، لا يوجد شيء معقد هنا، على الرغم من أن المصطلحات تبدو غامضة إلى حد ما ويمكن أن تربك أحيانًا حتى مطور البرامج المحترف.
الطبقات المتداخلة والداخلية
لذلك تسمى جميع الفئات الموجودة داخل الفئات الأخرى بالفئات المتداخلة.class OuterClass {
...
class NestedClass {
...
}
}
تسمى الفئات المتداخلة غير الثابتة بالفئات الداخلية ، وتسمى الفئات الثابتة بالفئات المتداخلة الثابتة .
class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
وبالتالي، فإن جميع الفئات الداخلية متداخلة، ولكن ليست جميع الفئات المتداخلة داخلية. هذه هي التعاريف الرئيسية. تعد الفئات الداخلية نوعًا من آليات الأمان في Java. نحن نعلم أنه لا يمكن ربط الفصل العادي بمعدّل وصول خاص. ومع ذلك، إذا كان فصلنا عضوًا في فصل آخر، فيمكن جعل الطبقة الداخلية خاصة. تُستخدم هذه الميزة أيضًا للوصول إلى أعضاء الفصل الخاص.
مثال الطبقة الداخلية
لذلك، دعونا نحاول إنشاء فئة ما، وداخلها — فئة أخرى. تخيل نوعًا ما من وحدات التحكم في الألعاب. يوجد "صندوق" بحد ذاته، ويمكن توصيل وحدات معينة به. على سبيل المثال، وحدة تحكم اللعبة، عجلة القيادة، خوذة VR، والتي، كقاعدة عامة، لا تعمل بدون وحدة التحكم نفسها. هنا لدينا فئة GameConsole. يحتوي على حقلين وطريقة واحدة — start() . الفرق بين GameCosole والفئة التي اعتدنا عليها هو أنها تحتوي على فئة GameController داخلية .public class GameConsole {
private String model;
private int weight;
public void run() {
System.out.println("Game console is on");
}
public class GameController {
private String color;
public void start() {
System.out.println("start button is pressed");
}
public void x() {
System.out.println("x button is pressed");
}
public void y() {
System.out.println("y button is pressed");
}
public void a() {
System.out.println("a button is pressed");
}
public void b() {
System.out.println("b button is pressed");
}
public void mover() {
System.out.println("mover button is pressed");
}
}
}
في هذه المرحلة قد تتساءل: لماذا لا نجعل هذه الفئات "منفصلة"؟ ليس من الضروري جعلها متداخلة. في الواقع أنه من الممكن. بل يتعلق الأمر بالتصميم الصحيح للفصول من حيث استخدامها. يتم إنشاء الفئات الداخلية لتسليط الضوء في البرنامج على كيان يرتبط ارتباطًا وثيقًا بكيان آخر. تعد وحدة التحكم أو خوذة الواقع الافتراضي على سبيل المثال من مكونات وحدة التحكم. نعم، يمكن شراؤها بشكل منفصل عن وحدة التحكم، ولكن لا يمكن استخدامها بدونها. إذا جعلنا كل هذه الفئات منفصلة عن الفئات العامة، فمن الممكن أن يحتوي برنامجنا، على سبيل المثال، على الكود التالي:
public class Main {
public static void main(String[] args) {
GameController controller = new GameController();
controller.x();
}
}
ما يحدث في هذه الحالة ليس واضحًا، نظرًا لأن وحدة التحكم نفسها لا تعمل بدون وحدة تحكم. لقد أنشأنا كائن وحدة تحكم اللعبة. لقد أنشأنا كائنه الفرعي – وحدة التحكم في اللعبة. والآن يمكننا اللعب، فقط اضغط على المفاتيح الصحيحة. يتم استدعاء الأساليب التي نحتاجها على الكائنات الصحيحة. كل شيء بسيط ومريح. في هذا المثال، يؤدي استخراج وحدة التحكم في اللعبة إلى تحسين التغليف (نقوم بإخفاء تفاصيل أجزاء وحدة التحكم داخل الفئة المقابلة)، ويسمح بتجريد أكثر تفصيلاً. لكن إذا قمنا، على سبيل المثال، بإنشاء برنامج يحاكي متجرًا يمكنك من خلاله شراء خوذة أو وحدة تحكم VR بشكل منفصل، فسيفشل هذا المثال. من الأفضل إنشاء وحدة تحكم في الألعاب بشكل منفصل. لنأخذ مثالا آخر. لقد ذكرنا أعلاه أنه يمكننا جعل الطبقة الداخلية خاصة ونسميها من الطبقة الخارجية. فيما يلي مثال على هذه الفئات.
class OuterClass {
// inner class
private class InnerClass {
public void print() {
System.out.println("We are in the inner class...");
}
}
// method of outer class. We are create an inner class from the method of outer one
void display() {
InnerClass inner = new InnerClass();
inner.print();
}
}
هنا OuterClass هي الفئة الخارجية، InnerClass هي الفئة الداخلية، وdisplay() هي الطريقة التي نقوم من خلالها بإنشاء كائن من الفئة الداخلية. لنكتب الآن فصلًا تجريبيًا بالطريقة الرئيسية حيث سنقوم باستدعاء طريقة العرض () .
public class OuterDemoMain {
public static void main(String args[]) {
// create an object of the outer class
OuterDemo outer = new OuterDemo();
outer.display();
}
}
إذا قمت بتشغيل هذا البرنامج، سوف تحصل على النتيجة التالية:
نحن في الطبقة الداخلية..
تصنيف الطبقات الداخلية
تنقسم الفئات الداخلية نفسها أو الفئات غير الثابتة المتداخلة إلى ثلاث مجموعات.- الطبقة الداخلية كما هي. فئة واحدة فقط غير ثابتة داخل الفئة الأخرى كما أوضحنا أعلاه باستخدام مثال GameConsole و GameController .
- الطبقة الداخلية للطريقة المحلية هي فئة داخل الطريقة.
- فئة داخلية مجهولة.
طريقة الطبقة الداخلية المحلية
في Java، يمكنك كتابة فصل دراسي داخل إحدى الطرق وهو نوع محلي. مثل المتغيرات المحلية، نطاق الفئة الداخلية محدود داخل الطريقة. لا يمكن إنشاء فئة داخلية للطريقة المحلية إلا ضمن الطريقة التي يتم فيها تعريف الفئة الداخلية. دعونا نوضح كيفية استخدام الطبقة الداخلية للطريقة المحلية.public class OuterDemo2 {
//instance method of the outer class OuterDemo2
void myMethod() {
String str = "and it's a value from OuterDemo2 class' myMethod ";
// method-local inner class
class methodInnerDemo {
public void print() {
System.out.println("Here we've got a method inner class... " );
System.out.println(str);
}
}
// Access to the inner class
methodInnerDemo inn = new methodInnerDemo();
inn.print();
}
}
سنقوم الآن بكتابة فصل تجريبي بالطريقة الرئيسية حيث سنقوم باستدعاء الطريقة الخارجية () .
public class OuterDemoMain {
public static void main(String args[]) {
OuterDemo2 outer = new OuterDemo2();
outer.myMethod();
}
}
الإخراج هو:
لدينا هنا طريقة الطبقة الداخلية... وهي قيمة من myMethod فئة OuterDemo2
الطبقة الداخلية مجهولة
تسمى الفئة الداخلية التي تم الإعلان عنها بدون اسم فئة بفئة داخلية مجهولة. عندما نعلن عن فئة داخلية مجهولة، فإننا نقوم بإنشاء مثيل لها على الفور. عادة، يتم استخدام هذه الفئات عندما تحتاج إلى تجاوز فئة أو أسلوب واجهة.abstract class OuterDemo3 {
public abstract void method();
}
class outerClass {
public static void main(String args[]) {
OuterDemo3 inner = new OuterDemo3() {
public void method() {
System.out.println("Here we've got an example of an anonymous inner class");
}
};
inner.method();
}
}
الإخراج هنا:
هنا لدينا مثال على فئة داخلية مجهولة...
فئة داخلية مجهولة كوسيطة
يمكنك أيضًا تمرير فئة داخلية مجهولة كوسيطة للطريقة. هنا مثال.interface OuterDemo4 {
String hello();
}
class NewClass {
// accepts the object of interface
public void displayMessage(OuterDemo4 myMessage) {
System.out.println(myMessage.hello());
System.out.println("example of anonymous inner class as an argument");
}
public static void main(String args[]) {
NewClass newClass = new NewClass();
//here we pass an anonymous inner class as an argument
newClass.displayMessage(new OuterDemo4() {
public String hello() {
return "Hello!";
}
});
}
}
الإخراج هنا:
مرحبًا! مثال على الطبقة الداخلية المجهولة كوسيطة
لتعزيز ما تعلمته، نقترح عليك مشاهدة درس فيديو من دورة Java الخاصة بنا
GO TO FULL VERSION