شنبه ۲۹ دي ۱۴۰۳
Tut24 آموزش برنامه نویسی و مجله تخصصی فناوری ورود/عضویت

آموزش جاوا - کلاس های داخلی

در این درس، ما درباره کلاس‌های داخلی جاوا صحبت خواهیم کرد.

کلاس‌های تو در تو

در جاوا، مانند متدها، متغیرهای یک کلاس می‌توانند یک کلاس دیگر را به عنوان عضو خود داشته باشند. نوشتن یک کلاس درون دیگر در جاوا مجاز است. کلاس نوشته شده درون آن، کلاس تو در تو نامیده می‌شود و کلاسی که کلاس داخلی را در خود نگه می‌دارد، کلاس بیرونی نامیده می‌شود.

نحو

در زیر نحوی برای نوشتن یک کلاس تو در تو آمده است. در اینجا، کلاس Outer_Demo کلاس بیرونی است و کلاس Inner_Demo کلاس داخلی است.


class Outer_Demo {
   class Inner_Demo {
   }
}

کلاس‌های تو در تو به دو نوع تقسیم می‌شوند:

  • کلاس‌های تو در تو غیر استاتیک (Non-static nested classes) - این‌ها اعضای غیر استاتیک یک کلاس هستند.

  • کلاس‌های تو در تو استاتیک (Static nested classes) - این‌ها اعضای استاتیک یک کلاس هستند.

کلاس‌های داخلی

کلاس‌های داخلی (کلاس‌های تو در تو غیر استاتیک)

کلاس‌های داخلی یک مکانیزم امنیتی در جاوا هستند. ما می‌دانیم که یک کلاس نمی‌تواند با محدودکننده دسترسی private مرتبط شود، اما اگر کلاس را به عنوان عضوی از کلاس دیگر داشته باشیم، آنگاه کلاس داخلی می‌تواند خصوصی باشد. همچنین از این مکانیزم برای دسترسی به اعضای خصوصی یک کلاس استفاده می‌شود.

کلاس‌های داخلی به سه نوع هستند که بستگی به نحو و مکان تعریف آن‌ها دارند:

  • کلاس داخلی (Inner Class)
  • کلاس داخلی محلی متد (Method-local Inner Class)
  • کلاس داخلی ناشناس (Anonymous Inner Class)

کلاس داخلی (Inner Class)

ایجاد یک کلاس داخلی بسیار ساده است. شما فقط باید یک کلاس درون یک کلاس بنویسید. برخلاف یک کلاس، یک کلاس داخلی می‌تواند خصوصی باشد و بعد از اعلام خصوصی بودن یک کلاس داخلی، از یک شی خارج از کلاس قابل دسترسی نمی‌باشد.

برنامه زیر نمونه‌ای از ایجاد یک کلاس داخلی و دسترسی به آن را نشان می‌دهد. در مثال داده شده، ما کلاس داخلی را خصوصی می‌کنیم و از طریق یک متد به کلاس دسترسی می‌یابیم.

مثال


class Outer_Demo {
   int num;
   
   // inner class
   private class Inner_Demo {
      public void print() {
         System.out.println("This is an inner class");
      }
   }
   
   // Accessing he inner class from the method within
   void display_Inner() {
      Inner_Demo inner = new Inner_Demo();
      inner.print();
   }
}
   
public class My_class {

   public static void main(String args[]) {
      // Instantiating the outer class 
      Outer_Demo outer = new Outer_Demo();
      
      // Accessing the display_Inner() method.
      outer.display_Inner();
   }
}

در اینجا می‌توانید مشاهده کنید که Outer_Demo کلاس بیرونی است، Inner_Demo کلاس داخلی است، display_Inner() متد است که درون آن کلاس داخلی را نمونه‌سازی می‌کنیم و این متد از متد main فراخوانی می‌شود.

اگر برنامه فوق را کامپایل و اجرا کنید، نتیجه زیر را دریافت خواهید کرد:

خروجی


This is an inner class.

دسترسی به اعضای خصوصی

همانطور که قبلاً ذکر شد، کلاس‌های داخلی همچنین برای دسترسی به اعضای خصوصی یک کلاس استفاده می‌شوند. فرض کنید یک کلاس اعضای خصوصی داشته باشد که به آن‌ها دسترسی داشته باشید. یک کلاس داخلی درون آن بنویسید، از یک متد درون کلاس داخلی، به عنوان مثال، getValue()، اعضای خصوصی را بازگردانده و در نهایت از یک کلاس دیگر (که می‌خواهید به اعضای خصوصی دسترسی داشته باشید) متد getValue() کلاس داخلی را فراخوانی کنید.

برای نمونه‌سازی کلاس داخلی، ابتدا باید کلاس بیرونی را نمونه‌سازی کنید. سپس با استفاده از شیء کلاس بیرونی، می‌توانید کلاس داخلی را به صورت زیر نمونه‌سازی کنید.


Outer_Demo outer = new Outer_Demo();
Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();

برنامه زیر نشان می‌دهد که چگونه با استفاده از کلاس داخلی، به اعضای خصوصی یک کلاس دسترسی پیدا کنیم.

مثال


class Outer_Demo {
   // private variable of the outer class
   private int num = 175;  
   
   // inner class
   public class Inner_Demo {
      public int getNum() {
         System.out.println("This is the getnum method of the inner class");
         return num;
      }
   }
}

public class My_class2 {

   public static void main(String args[]) {
      // Instantiating the outer class
      Outer_Demo outer = new Outer_Demo();
      
      // Instantiating the inner class
      Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
      System.out.println(inner.getNum());
   }
}

اگر برنامه فوق را کامپایل و اجرا کنید، نتیجه زیر را دریافت خواهید کرد:

خروجی


This is the getnum method of the inner class: 175

کلاس داخلی محلی متد (Method-local Inner Class)

در جاوا، ما می‌توانیم یک کلاس را درون یک متد بنویسیم و این یک نوع محلی خواهد بود. مانند متغیرهای محلی، محدوده کلاس داخلی تنها درون متد محدود است.

کلاس داخلی محلی متد تنها درون متدی که کلاس داخلی در آن تعریف شده است می‌تواند نمونه‌سازی شود. برنامه زیر نشان می‌دهد چگونه از یک کلاس داخلی محلی متد استفاده کنیم.

مثال


public class Outerclass {
   // instance method of the outer class 
   void my_Method() {
      int num = 23;

      // method-local inner class
      class MethodInner_Demo {
         public void print() {
            System.out.println("This is method inner class "+num);	   
         }   
      } // end of inner class
	   
      // Accessing the inner class
      MethodInner_Demo inner = new MethodInner_Demo();
      inner.print();
   }
   
   public static void main(String args[]) {
      Outerclass outer = new Outerclass();
      outer.my_Method();	   	   
   }
}

اگر برنامه فوق را کامپایل و اجرا کنید، نتیجه زیر را دریافت خواهید کرد:

خروجی


This is method inner class 23

کلاس داخلی ناشناس (Anonymous Inner Class)

کلاسی که بدون نام کلاس تعریف می‌شود به عنوان یک کلاس داخلی ناشناس شناخته می‌شود. در صورت استفاده از کلاس‌های داخلی ناشناس، آن‌ها را در همان زمان تعریف و نمونه‌سازی می‌کنیم. به طور کلی، آن‌ها هنگامی استفاده می‌شوند که نیاز دارید به یک متد یک کلاس یا یک رابط مجبور شوید متدی را override کنید. دستور زبان یک کلاس داخلی ناشناس به شرح زیر است:

دستور زبان


AnonymousInner an_inner = new AnonymousInner() {
   public void my_method() {
      ........
      ........
   }   
};

برنامه زیر نشان می‌دهد که چگونه با استفاده از کلاس داخلی ناشناس، متد یک کلاس را override کنیم.

مثال


abstract class AnonymousInner {
   public abstract void mymethod();
}

public class Outer_class {

   public static void main(String args[]) {
      AnonymousInner inner = new AnonymousInner() {
         public void mymethod() {
            System.out.println("This is an example of anonymous inner class");
         }
      };
      inner.mymethod();	
   }
}

اگر برنامه فوق را کامپایل و اجرا کنید، نتیجه زیر را دریافت خواهید کرد:

خروجی


This is an example of anonymous inner class

به همان روش، می‌توانید متدهای یک کلاس محسوب شده و همچنین متدهای یک رابط را با استفاده از یک کلاس داخلی ناشناس override کنید.

کلاس داخلی ناشناس به عنوان آرگومان

به طور کلی، اگر یک متد یک شیء از یک رابط، یک کلاس انتزاعی یا یک کلاس محسوب شده را پذیرفت، می‌توانیم رابط را پیاده‌سازی کرده، کلاس انتزاعی را گسترش داده و شیء را به متد منتقل کنیم. اگر آن کلاس باشد، می‌توانیم آن را مستقیما به متد منتقل کنیم.

اما در همه سه حالت، می‌توانید یک کلاس داخلی ناشناس را به متد منتقل کنید. در ادامه نحوه انتقال یک کلاس داخلی ناشناس به عنوان آرگومان یک متد آمده است:


obj.my_Method(new My_Class() {
   public void Do() {
      .....
      .....
   }
});

برنامه زیر نحوه انتقال یک کلاس داخلی ناشناس به عنوان آرگومان یک متد را نشان می‌دهد:

مثال


// interface
interface Message {
   String greet();
}

public class My_class {
   // method which accepts the object of interface Message
   public void displayMessage(Message m) {
      System.out.println(m.greet() +
         ", This is an example of anonymous inner class as an argument");  
   }

   public static void main(String args[]) {
      // Instantiating the class
      My_class obj = new My_class();

      // Passing an anonymous inner class as an argument
      obj.displayMessage(new Message() {
         public String greet() {
            return "Hello";
         }
      });
   }
}

اگر برنامه را کامپایل و اجرا کنید، نتیجه زیر را دریافت خواهید کرد −

خروجی


Hello, This is an example of anonymous inner class as an argument

کلاس تودرتو ثابت (Static Nested Class)

یک کلاس داخلی تودرتو که عضو ثابتی از کلاس بیرونی است، کلاس تودرتو ثابت است. این کلاس بدون نیاز به نمونه‌سازی کلاس بیرونی و با استفاده از سایر اعضای ثابت قابل دسترسی است. همانند اعضای ثابت، کلاس داخلی تودرتو ثابت دسترسی به متغیرها و متدهای نمونه‌ای کلاس بیرونی را ندارد. نحوه نوشتاری کلاس تودرتو ثابت به شرح زیر است −

نحوه نوشتاری


class MyOuter {
   static class Nested_Demo {
   }
}

نمونه‌سازی یک کلاس تودرتو ثابت (Static Nested Class) یکم تفاوتی با نمونه‌سازی یک کلاس داخلی دارد. برنامه زیر نحوه استفاده از یک کلاس تودرتو ثابت را نشان می‌دهد.

مثال


public class Outer {
   static class Nested_Demo {
      public void my_method() {
         System.out.println("This is my nested class");
      }
   }
   
   public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();	 
      nested.my_method();
   }
}

اگر برنامه بالا را کامپایل و اجرا کنید، نتیجه زیر را خواهید داشت −

خروجی


This is my nested class