CodeGym /Blog Java /Ngẫu nhiên /lớp ẩn danh

lớp ẩn danh

Xuất bản trong nhóm
CHÀO! Trong bài hôm nay chúng ta sẽ tiếp tục tìm hiểu chủ đề lớp lồng nhau. Bây giờ là lúc cho nhóm cuối cùng: các lớp bên trong ẩn danh. Hãy trở lại sơ đồ của chúng tôi: Lớp học ẩn danh - 2Giống như các lớp cục bộ mà chúng ta đã nói đến trong bài học trước, các lớp ẩn danh là một loại lớp bên trong... Chúng cũng có một số điểm tương đồng và khác biệt. Nhưng trước tiên, hãy đi sâu vào: chính xác tại sao chúng được gọi là "ẩn danh"? Để trả lời điều này, hãy xem xét một ví dụ đơn giản. Hãy tưởng tượng rằng chúng ta có một chương trình cơ bản liên tục chạy và làm một việc gì đó. Chúng tôi muốn tạo một hệ thống giám sát cho chương trình này, bao gồm một số mô-đun. Một mô-đun sẽ theo dõi các chỉ số chung về hiệu suất và duy trì nhật ký. Cái thứ hai sẽ đăng ký và ghi lại lỗi trong nhật ký lỗi. Thứ ba sẽ theo dõi hoạt động đáng ngờ: ví dụ: nỗ lực truy cập trái phép và những thứ khác liên quan đến bảo mật. Bởi vì về bản chất, cả ba mô-đun chỉ cần bắt đầu từ đầu chương trình và chạy ở chế độ nền,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 lớp cụ thể sẽ thực hiện nó:

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!");
   }
}
Có vẻ như mọi thứ đều theo thứ tự. Chúng tôi có một hệ thống khá mạch lạc được tạo thành từ một số mô-đun. Mỗi người trong số họ có hành vi riêng của mình. Nếu chúng tôi cần các mô-đun mới, chúng tôi có thể thêm chúng, bởi vì chúng tôi có một giao diện khá dễ thực hiện. Nhưng hãy nghĩ xem hệ thống giám sát của chúng ta sẽ hoạt động như thế nào. Lớp học ẩn danh - 3Về cơ bản, chúng ta chỉ cần tạo 3 đối tượng — GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule— và gọi startMonitoring()phương thức trên mỗi đối tượng đó. Đó là, tất cả những gì chúng ta cần làm là tạo 3 đối tượng và gọi 1 phương thức trên chúng.

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();
   }
}
Đầu ra bảng điều khiển:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Và với ít công việc như vậy, chúng tôi đã viết toàn bộ hệ thống: 3 lớp và một giao diện! Và tất cả điều này để đạt được 6 dòng mã. Mặt khác, lựa chọn của chúng tôi là gì? Chà, thật không hay khi chúng tôi viết những lớp học "một lần" này. Nhưng làm thế nào chúng ta có thể khắc phục điều này? Ở đây các lớp bên trong ẩn danh đến để giải cứu chúng tôi! Đây là những gì họ trông giống như trong trường hợp của chúng tôi:

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();
   }
}
Hãy tìm hiểu những gì đang xảy ra! Có vẻ như chúng ta đang tạo một đối tượng giao diện:

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
Nhưng từ lâu chúng ta đã biết rằng chúng ta không thể tạo các đối tượng giao diện! Và vì vậy nó là - nó không thể. Trên thực tế, đó không phải là những gì chúng tôi đang làm. Khi chúng ta viết:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
những điều sau đây xảy ra bên trong máy Java:
  1. Một lớp Java chưa được đặt tên được tạo để triển khai MonitoringSystemgiao diện.
  2. Khi trình biên dịch nhìn thấy một lớp như vậy, nó yêu cầu bạn thực hiện tất cả các phương thức của MonitoringSystemgiao diện (chúng tôi đã làm điều này 3 lần).
  3. Một đối tượng của lớp này được tạo. Hãy chú ý đến mã:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Có dấu chấm phẩy ở cuối! Nó ở đó vì một lý do. Chúng tôi đồng thời khai báo lớp (sử dụng dấu ngoặc nhọn) và tạo một thể hiện của nó (sử dụng ();). Mỗi đối tượng trong số ba đối tượng của chúng ta sẽ ghi đè startMonitoring()phương thức theo cách riêng của nó. Cuối cùng, chúng tôi chỉ cần gọi phương thức này trên mỗi người trong số họ:

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Đầu ra bảng điều khiển:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Đó là nó! Chúng tôi đã đạt được mục tiêu của mình: chúng tôi đã tạo ba MonitoringSystemđối tượng, ghi đè một phương thức theo ba cách khác nhau và gọi nó ba lần. Cả ba mô-đun đã được gọi thành công và đang chạy. Đồng thời, cấu trúc của chương trình của chúng tôi đã trở nên đơn giản hơn nhiều! Xét cho cùng, các lớp GeneralIndicatorMonitoringModule, ErrorMonitoringModule, và SecurityModulegiờ đây có thể bị xóa hoàn toàn khỏi chương trình! Đơn giản là chúng tôi không cần chúng — chúng tôi đã làm rất tốt khi không có chúng. Nếu mỗi lớp ẩn danh của chúng tôi cần một số hành vi khác nhau, ví dụ: các phương thức cụ thể của riêng nó mà các lớp khác không có, chúng tôi có thể dễ dàng thêm chúng:

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");
   }
};
Tài liệu của Oracle cung cấp một khuyến nghị tốt : "Sử dụng [các lớp ẩn danh] nếu bạn chỉ cần sử dụng một lớp cục bộ một lần." Một lớp ẩn danh là một lớp bên trong chính thức. Theo đó, nó có quyền truy cập vào các biến của lớp bên ngoài, bao gồm các biến tĩnh và biến riêng:

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;
           }
       };
   }
}
Chúng có điểm chung với các lớp cục bộ: chúng chỉ hiển thị bên trong phương thức mà chúng được khai báo. Trong ví dụ trên, mọi nỗ lực truy cập errorModuleđối tượng bên ngoài main()phương thức sẽ không thành công. Và còn một hạn chế quan trọng nữa mà các lớp ẩn danh kế thừa từ các “tổ tiên” của chúng (các lớp bên trong): một lớp ẩn danh không thể chứa các biến và phương thức tĩnh . Trong ví dụ trên, nếu chúng ta cố gắng làm cho getCurrentErrorCount()phương thức tĩnh, trình biên dịch sẽ báo lỗi:

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

   return currentErrorCount;
}
Chúng tôi nhận được kết quả tương tự nếu chúng tôi cố gắng khai báo một biến tĩnh:

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!");
   }

};
Và bài học hôm nay của chúng ta đã kết thúc! Nhưng mặc dù chúng tôi đã điều tra nhóm lớp lồng nhau cuối cùng, chúng tôi vẫn chưa kết thúc chủ đề này. Chúng ta sẽ tìm hiểu gì thêm về các lớp lồng nhau? Bạn chắc chắn sẽ tìm ra sớm thôi! :)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION