CodeGym /وبلاگ جاوا /Random-FA /کلاس های ناشناس
John Squirrels
مرحله
San Francisco

کلاس های ناشناس

در گروه منتشر شد
سلام! در درس امروز به بررسی مبحث کلاس های تو در تو ادامه می دهیم. اکنون نوبت به آخرین گروه می رسد: کلاس های داخلی ناشناس. برگردیم به نمودار خود: کلاس های ناشناس - 2مانند کلاس های محلی که در درس گذشته در مورد آنها صحبت کردیم، کلاس های بی نام نیز نوعی کلاس درونی هستند... آنها نیز چندین شباهت و تفاوت دارند. اما ابتدا بیایید به این موضوع بپردازیم: چرا دقیقاً آنها را "ناشناس" می نامند؟ برای پاسخ به این، یک مثال ساده را در نظر بگیرید. تصور کنید که ما یک برنامه اساسی داریم که دائماً در حال اجرا است و کاری انجام می دهد. ما می خواهیم یک سیستم نظارتی برای این برنامه ایجاد کنیم که از چندین ماژول تشکیل شده است. یک ماژول شاخص های کلی عملکرد را ردیابی می کند و یک گزارش را حفظ می کند. دومی خطاها را در یک گزارش خطا ثبت و ثبت می کند. مورد سوم فعالیت های مشکوک را ردیابی می کند: به عنوان مثال، تلاش برای دسترسی غیرمجاز و سایر موارد مرتبط با امنیت. از آنجا که هر سه ماژول در اصل باید به سادگی از ابتدای برنامه شروع شده و در پس زمینه اجرا شوند، ایجاد یک رابط مشترک برای آنها ایده خوبی خواهد بود:

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 کلاس بتن آن را اجرا خواهند کرد:

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
به نظر می رسد که همه چیز مرتب است. ما یک سیستم بسیار منسجم داریم که از چندین ماژول تشکیل شده است. هر کدام از آنها رفتار خاص خود را دارند. اگر به ماژول‌های جدید نیاز داریم، می‌توانیم آن‌ها را اضافه کنیم، زیرا رابطی داریم که پیاده‌سازی آن بسیار آسان است. اما بیایید به این فکر کنیم که سیستم نظارتی ما چگونه کار خواهد کرد. کلاس های ناشناس - 3اساسا، ما فقط باید 3 شی - GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule- ایجاد کنیم و startMonitoring()متد را روی هر یک از آنها فراخوانی کنیم. یعنی تنها کاری که باید انجام دهیم این است که 3 شی ایجاد کنیم و 1 متد را روی آنها فراخوانی کنیم.

public class Main {

   public static void main(String[] args) {

       GeneralIndicatorMonitoringModule generalModule = new GeneralIndicatorMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
خروجی کنسول:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
و با این کار کوچک، کل سیستم را نوشته ایم: 3 کلاس و یک رابط! و همه اینها برای دستیابی به 6 خط کد. از طرفی گزینه های ما چیست؟ خوب، خیلی باحال نیست که ما این کلاس های "یک بار" را نوشتیم. اما چگونه می توانیم این را برطرف کنیم؟ اینجا کلاس های داخلی ناشناس به کمک ما می آیند! در مورد ما به این صورت است:

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
بیایید بفهمیم چه خبر است! به نظر می رسد که در حال ایجاد یک شیء رابط هستیم:

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
اما ما مدتهاست می دانیم که نمی توانیم اشیاء رابط ایجاد کنیم! و همینطور است - غیرممکن است. در واقع، این کاری نیست که ما انجام می دهیم. وقتی می نویسیم:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
موارد زیر در داخل ماشین جاوا اتفاق می افتد:
  1. یک کلاس جاوا بدون نام ایجاد می شود که MonitoringSystemرابط را پیاده سازی می کند.
  2. هنگامی که کامپایلر چنین کلاسی را می بیند، از شما می خواهد که تمام متدهای رابط را پیاده سازی کنید MonitoringSystem(ما این کار را 3 بار انجام دادیم).
  3. یک شی از این کلاس ایجاد می شود. به کد توجه کنید:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
در پایان یک نقطه ویرگول وجود دارد! به دلیلی آنجاست ما به طور همزمان کلاس را اعلام می کنیم (با استفاده از بریس های فرفری) و یک نمونه از آن را ایجاد می کنیم (با استفاده از ();). هر یک از سه شیء ما startMonitoring()به روش خود روش را لغو می کند. در نهایت، ما به سادگی این روش را برای هر یک از آنها فراخوانی می کنیم:

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
خروجی کنسول:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
خودشه! ما به هدف خود رسیدیم: ما سه MonitoringSystemشی ایجاد کردیم، یک روش را به سه روش مختلف تحت تأثیر قرار دادیم و سه بار آن را فراخوانی کردیم. هر سه ماژول با موفقیت فراخوانی شده و در حال اجرا هستند. در عین حال، ساختار برنامه ما بسیار ساده تر شده است! پس از همه، کلاس های GeneralIndicatorMonitoringModule، ErrorMonitoringModuleو SecurityModuleاکنون می توانند به طور کامل از برنامه حذف شوند! ما به سادگی به آنها نیاز نداریم - ما بدون آنها کار بزرگی انجام دادیم. اگر هر یک از کلاس های ناشناس ما به رفتارهای متفاوتی نیاز دارد، به عنوان مثال روش های خاص خود را که بقیه ندارند، می توانیم به راحتی آنها را اضافه کنیم:

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
مستندات اوراکل یک توصیه خوب ارائه می دهد : "اگر فقط یک بار نیاز به استفاده از یک کلاس محلی دارید، از [کلاس های ناشناس] استفاده کنید." یک کلاس ناشناس یک کلاس داخلی تمام عیار است. بر این اساس، به متغیرهای کلاس خارجی از جمله متغیرهای استاتیک و خصوصی دسترسی دارد:

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
آنها چیزی مشترک با کلاس های محلی دارند: آنها فقط در داخل متدی که در آن اعلان شده اند قابل مشاهده هستند. در مثال بالا، هرگونه تلاش برای دسترسی به errorModuleشی خارج از main()متد با شکست مواجه خواهد شد. و یک محدودیت مهم دیگر وجود دارد که کلاس‌های ناشناس از اجدادشان (کلاس‌های داخلی) به ارث می‌برند: یک کلاس ناشناس نمی‌تواند شامل متغیرها و متدهای ثابت باشد . در مثال بالا، اگر بخواهیم getCurrentErrorCount()متد را ثابت کنیم، کامپایلر یک خطا ایجاد می کند:

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
اگر بخواهیم یک متغیر استاتیک را اعلام کنیم، همان نتیجه را دریافت می کنیم:

MonitoringSystem errorModule = new MonitoringSystem() {

   // Error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
و درس امروز ما به پایان رسیده است! اما با وجود اینکه آخرین گروه کلاس‌های تودرتو را بررسی کرده‌ایم، هنوز این مبحث را تمام نکرده‌ایم. در مورد کلاس های تودرتو چه چیز بیشتری یاد خواهیم گرفت؟ مطمئناً به زودی خواهید فهمید! :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION