فئة داخلية في Java

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

  1. الفصل المتداخل الثابت

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

    OuterClass.StaticNestedClass nestedObject =
         new OuterClass.StaticNestedClass();
    
  2. الصف الداخلي في جافا

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

    OuterClass outerObject = new OuterClass();
    OuterClass.InnerClass innerObject = outerObject.new InnerClass();
    

هناك نوعان خاصان من فئات جافا الداخلية.

  1. الصنف الداخلي المحلي

    إذا تم تعريف صنف داخلي في جسم الطريقة، يُعرف بأنه صنف داخلي محلي. نظرًا لأن الصنف الداخلي المحلي غير مرتبط بكائن، لا يمكننا استخدام الكلمات المفتاحية الخاصة بالوصول private أو public أو protected معه. الكلمات المفتاحية المسموح بها هي فقط abstract أو final. يمكن للصنف الداخلي المحلي الوصول إلى جميع أعضاء الصنف الخارجي والمتغيرات المحلية النهائية في النطاق الذي يتم فيه تعريفه. بالإضافة إلى ذلك، يمكنه أيضًا الوصول إلى متغير محلي غير نهائي للطريقة التي يتم فيها تعريفه، ولكن لا يمكنه تعديلها. لذلك، إذا حاولت طباعة قيمة المتغير المحلي غير النهائي، فسيتم السماح بذلك ولكن إذا حاولت تغيير قيمتها من داخل صنف الطريقة الداخلي المحلي، فستحصل على خطأ في وقت الترجمة. يمكن تعريف الصنف الداخلي المحلي على النحو التالي:

    package com.journaldev.innerclasses;
    
    public class MainClass {
    
    	private String s_main_class;
    
    	public void print() {
    		String s_print_method = "";
    		// الصنف الداخلي المحلي داخل الطريقة
    		class Logger {
    			// قادر على الوصول إلى متغيرات الصنف الخارجي
    			String name = s_main_class; 
    			// قادر على الوصول إلى متغيرات الطريقة غير النهائية
    			String name1 = s_print_method; 
    
    			public void foo() {
    				String name1 = s_print_method;
    				// الكود أدناه سيثير خطأ في وقت الترجمة:
    				// تم تعريف المتغير المحلي s_print_method في نطاق محيطي يجب أن يكون نهائيًا أو نهائيًا بشكل فعّال
    				// s_print_method= ":";
    			}
    		}
    		// تعيين الصنف الداخلي المحلي في الطريقة للاستخدام
    		Logger logger = new Logger();
    
    	}
    }
    

    يمكننا تعريف صنف داخلي محلي داخل أي كتلة أيضًا، مثل الكتلة الثابتة، كتلة if-else الخ. ومع ذلك، في هذه الحالة، ستكون نطاق الصنف محدودًا للغاية.

    public class MainClass {
    
    	static {
    		class Foo {
    			
    		}
    		Foo f = new Foo();
    	}
    	
    	public void bar() {
    		if(1 < 2) {
    			class Test {
    				
    			}
    			Test t1 = new Test();
    		}
    		// سيثير الأمر أدناه خطأ بسبب نطاق الصنف
    		//Test t = new Test();
    		//Foo f = new Foo();
    	}
    }
    
  2. الصف الداخلي المجهول

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

هنا يوجد صف جافا يوضح كيفية تعريف الصف الداخلي الجافا، الصف الثابت المضمن، الصف الداخلي المحلي، والصف الداخلي المجهول. OuterClass.java

package com.journaldev.nested;

import java.io.File;
import java.io.FilenameFilter;

public class OuterClass {
    
    private static String name = "OuterClass";
    private int i;
    protected int j;
    int k;
    public int l;

    //بناء فئة الـOuterClass
    public OuterClass(int i, int j, int k, int l) {
        this.i = i;
        this.j = j;
        this.k = k;
        this.l = l;
    }

    public int getI() {
        return this.i;
    }

    //فئة مضمنة ثابتة، يمكنها الوصول إلى المتغيرات/الطرق الثابتة للفئة الخارجية
    static class StaticNestedClass {
        private int a;
        protected int b;
        int c;
        public int d;

        public int getA() {
            return this.a;
        }

        public String getName() {
            return name;
        }
    }

    //فئة داخلية، غير ثابتة ويمكنها الوصول إلى جميع المتغيرات/الطرق للفئة الخارجية
    class InnerClass {
        private int w;
        protected int x;
        int y;
        public int z;

        public int getW() {
            return this.w;
        }

        public void setValues() {
            this.w = i;
            this.x = j;
            this.y = k;
            this.z = l;
        }

        @Override
        public String toString() {
            return "w=" + w + ":x=" + x + ":y=" + y + ":z=" + z;
        }

        public String getName() {
            return name;
        }
    }

    //فئة داخلية محلية
    public void print(String initial) {
        //فئة داخلية محلية inside the method
        class Logger {
            String name;

            public Logger(String name) {
                this.name = name;
            }

            public void log(String str) {
                System.out.println(this.name + ": " + str);
            }
        }

        Logger logger = new Logger(initial);
        logger.log(name);
        logger.log("" + this.i);
        logger.log("" + this.j);
        logger.log("" + this.k);
        logger.log("" + this.l);
    }

    //فئة داخلية مجهولة
    public String[] getFilesInDir(String dir, final String ext) {
        File file = new File(dir);
        //فئة داخلية مجهولة implementing FilenameFilter interface
        String[] filesList = file.list(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(ext);
            }

        });
        return filesList;
    }
}

هنا برنامج الاختبار الذي يظهر كيفية إنشاء واستخدام الفئة الداخلية في جافا. InnerClassTest.java

package com.journaldev.nested;

import java.util.Arrays;
//يمكن استخدام الفئات المضمنة في الاستيراد لسهولة الإنشاء
import com.journaldev.nested.OuterClass.InnerClass;
import com.journaldev.nested.OuterClass.StaticNestedClass;

public class InnerClassTest {

    public static void main(String[] args) {
        OuterClass outer = new OuterClass(1,2,3,4);
        
        //مثال على الفئات المضمنة الثابتة
        StaticNestedClass staticNestedClass = new StaticNestedClass();
        StaticNestedClass staticNestedClass1 = new StaticNestedClass();
        
        System.out.println(staticNestedClass.getName());
        staticNestedClass.d=10;
        System.out.println(staticNestedClass.d);
        System.out.println(staticNestedClass1.d);
        
        //مثال على الفئة الداخلية
        InnerClass innerClass = outer.new InnerClass();
        System.out.println(innerClass.getName());
        System.out.println(innerClass);
        innerClass.setValues();
        System.out.println(innerClass);
        
        //استدعاء الطريقة باستخدام الفئة الداخلية المحلية
        outer.print("Outer");
        
        //استدعاء الطريقة باستخدام الفئة الداخلية المجهولة
        System.out.println(Arrays.toString(outer.getFilesInDir("src/com/journaldev/nested", ".java")));
        
        System.out.println(Arrays.toString(outer.getFilesInDir("bin/com/journaldev/nested", ".class")));
    }

}

هنا إخراج برنامج مثال الفئة الداخلية في جافا أعلاه.

OuterClass
10
0
OuterClass
w=0:x=0:y=0:z=0
w=1:x=2:y=3:z=4
Outer: OuterClass
Outer: 1
Outer: 2
Outer: 3
Outer: 4
[NestedClassTest.java, OuterClass.java]
[NestedClassTest.class, OuterClass$1.class, OuterClass$1Logger.class, OuterClass$InnerClass.class, OuterClass$StaticNestedClass.class, OuterClass.class]

لاحظ أنه عند تجميع الفئة الخارجية، يتم إنشاء ملفات فئة منفصلة للفئة الداخلية، والفئة الداخلية المحلية، والفئة الداخلية الثابتة.

فوائد الفئة الداخلية في جافا

  1. إذا كانت فئة مفيدة لفئة واحدة فقط، فإنه من المنطق الاحتفاظ بها مضمنة ومعًا. إنه يساعد في تجميع الفئات.
  2. تنفذ الفئات الداخلية في جافا التجزئة. يجب ملاحظة أن الفئات الداخلية يمكنها الوصول إلى أعضاء الفئة الخارجية الخاصة وفي نفس الوقت يمكننا إخفاء الفئة الداخلية عن العالم الخارجي.
  3. إبقاء الفئة الصغيرة داخل الفئات على مستوى أعلى يضع الشفرة بالقرب من المكان الذي يتم استخدامه فيه ويجعل الشفرة أكثر قابلية للقراءة والصيانة.

هذا كل شيء بخصوص الفئة الداخلية في جافا.

Source:
https://www.digitalocean.com/community/tutorials/java-inner-class