Nested Classes (P1)
Ngôn ngữ Java cho phép bạn định nghĩa một class nằm ở bên trong một class khác. Nó được gọi là nested class và được minh họa ở phía dưới: class OuterClass { ... class NestedClass { ... } } Nested class được chia thành 2 loại: static và non-static. Nested classes được khai ...
Ngôn ngữ Java cho phép bạn định nghĩa một class nằm ở bên trong một class khác. Nó được gọi là nested class và được minh họa ở phía dưới:
class OuterClass { ... class NestedClass { ... } }
Nested class được chia thành 2 loại: static và non-static. Nested classes được khai báo với static được gọi là static nested classes , Non-static nested classes được gọi là inner classes.
class OuterClass { ... static class StaticNestedClass { ... } class InnerClass { ... } }
Một nested class là một member của class chứa nó. Non-static nested classes (inner classes) có thể truy cập đến những member khác của outer class, ngay cả khi chúng được khai báo là private. Static nested classes thì không thể truy cập đến những member khác của outer class. Cũng giống như một member của OuterClass, một nested class có thể khai báo là private, public, protected hoặc package private. (Nhắc lại là outer classes chỉ có thể khai báo là public hoặc package private).
Why Use Nested Classes?
Những lý do cho việc sử dụng nested classes bao gồm:
- Đây là một cách để nhóm các class chỉ được sử dụng ở một chỗ lại với nhau một cách hợp lý : Nếu một class chỉ dùng được từ một class khác, thì sẽ hợp lý khi gắn nó vào trong class kia và giữ chúng cùng nhau. Việc lồng vào như vậy sẽ giúp cho package được tổ chức hợp lý hơn.
- Giúp tăng sự gọn gàng: Xem xét 2 top-level class, A và B. B cần truy cập đến những member của A tuy nhiên những member đó lại được khai báo là private. Bằng việc giấu class B ở bên trong A, những member của A có thể khai báo là private mà B vẫn có thể truy cập được chúng. Thêm nữa, B có thể được giấu với phần còn lại của project.
- Có thể giúp code dễ đọc và dễ maintain hơn: Lồng những class nhỏ vào bên trong top-level class giúp cho những dòng code ở gần hơn với nơi chúng được sử dụng.
Static Nested Classes
Giống như class methods và variables, một static nested class được liên kết với outer class của nó. Và giống như static method, một static nested class không thể trực tiếp gọi đến các biến hay method được định nghĩa bên trong class chứa nó, nó chỉ có thể sử dụng chúng thông qua một object reference.
Note: Một static nested class tương tác với những member của outer class (và những class khác) giống như mọi top-level class khác. Kết quả là một static nested class hoạt động giống như một top-level class, nhưng được đặt bên trong một top-level class khác, để thuận lợi cho việc đóng gói.
Static nested classes được truy cập bằng cách sử dụng tên của class chứa nó: OuterClass.StaticNestedClass
Ví dụ, để tạo một object với static nested class, sử dụng cú pháp:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Inner Classes
Giống như instance methods và variables, một inner class được liên kết với một instance của class chứa nó và có thể trực tiếp truy cập đến những method hay field. Ngoài ra, vì inner class được liên kết với một instance, không thể khai báo bất kì static member nào bên trong nó Những instance của một inner class tồn tại cùng với một instance của outer class. Xem xét ví dụ bên dưới:
class OuterClass { ... class InnerClass { ... } }
Một instance của InnerClass chỉ có thể tồn tại khi có một khởi tạo của OuterClass và nó có thể trực tiếp truy cập đến những method hay field của instance của OuterClass.
Để khởi tạo một inner class, trước tiên bạn phải khởi tạo outer class. Sau đó khởi tạo inner object với cú pháp: OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Inner classes có 2 loại riêng biệt là: local classes và anonymous classes.
Shadowing
Nếu một khai báo (chẳng hạn như như một member variable hoặc parameter ) trong một scope nào đó (chẳng hạn như một inner class hoặc một method definiton) có tên giống một khai báo khác ở trong scope chứa nó, thì khai báo đó shadows khai báo ở trong scope chứa nó. Bạn không thể gọi đến một khai báo shadowed chỉ với tên của nó. Ví dụ ShadowTest bên dưới sẽ chứng minh điều đó:
public class ShadowTest { public int x = 0; class FirstLevel { public int x = 1; void methodInFirstLevel(int x) { System.out.println("x = " + x); System.out.println("this.x = " + this.x); System.out.println("ShadowTest.this.x = " + ShadowTest.this.x); } } public static void main(String... args) { ShadowTest st = new ShadowTest(); ShadowTest.FirstLevel fl = st.new FirstLevel(); fl.methodInFirstLevel(23); } }
Kết quả cho ví dụ trên:
x = 23 this.x = 1 ShadowTest.this.x = 0
Trong ví dụ này đã định nghĩa 3 biến cùng tên là x: một là member variable của class ShadowTest, hai là member variable của inner class FirstLevel, và ba là tham số trong method methodInFirstLevel. x là tham số của method methodInFirstLevel shadows biến x của inner class FirstLevel. Vì vậy, khi bạn sử dụng x ở trong method methodInFirstLevel, nó sẽ gọi đến tham số của method, để gọi đến member variable của FirstLevel, sử dụng keyword sau đây để gọi đến scope chứa nó: System.out.println("this.x = " + this.x);
Có thể gọi đến những member variables của những outer class lớn hơn bằng cách dùng tên của outer class. Ví dụ, câu lệnh bên dưới sẽ truy cập đến member variable của class ShadowTest từ method methodInFirstLevel: System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
Nguồn bài viết
https://docs.oracle.com/javase/tutorial/java