Bây giờ thì chúng ta đã có thể có rất nhiều các class
có liên quan với nhau theo mô hình kế thừa hoặc tính năng bổ trợ. Lúc này mối quan tâm tiếp theo là câu chuyện sắp xếp và quản lý các tệp mã nguồn .java
.
Package
Khái niệm package
trong Java
được hiểu là một tên miền namespace
, nơi mà chúng ta có thể sử dụng các tên class
mà không phải lo chuyện trùng lặp với các class
khác ở bên ngoài không gian đó.
Và bởi vì Java
quy định mỗi tệp mã nguồn .java
sẽ phải được đặt tên trùng với class
định nghĩa trong code của tệp đó, vì vậy nên chúng ta cũng có thể hiểu rằng một package
là một thư mục chứa các tệp code. Chúng ta hiển nhiên không thể có nhiều tệp code mã nguồn .java
trùng tên trong cùng một thư mục được, nhưng lại chắc chắn có thể sử dụng lại các tên class
trong các thư mục khác nhau.
Ví dụ:
/learn-java
├── app
│ ├── Main.java
│ ├── data
│ │ └── Person.java
│ └── delegate
│ └── Person.java
└── src.txt
package app.data; // -- package declaration class Person { String name = ""; int age = 0; Person (String $name, int $age) { this.name = $name; this.age = $age; } } // -- end class
Mặc định thì các class
sẽ chỉ khả dụng trong không gian của package
chứa chúng, và thêm vào đó thì Java
xem các package
là đồng đẳng và không liên quan tới nhau; Vì vậy nên mặc dù package app
về mặt quản lý thư mục thì đúng là có chứa hai package
con là app.data
và app.delegate
, nhưng trong logic vận hành thì code của Main.java
sẽ phải tham chiếu tới các class
khác bằng cách chỉ rõ tên miền đang chứa hoặc thực hiện thao tác import
giống như chúng ta đã sử dụng package java.io
trước đó.
Ví dụ:
app.data.Person $me = new app.data.Person ("Semi Dev_", 1001);
Hoặc:
package app; import app.data.Person;
import java.io.*; class Main { public static void main (String[] $args) { Person $me = new Person ("Semi Dev_", 1001); System.out.println ($me.name); } } // -- end class
Tuy nhiên, để các thao tác tham chiếu đã nói ở trên có thể hoạt động được thì chúng ta còn phải xem xét thêm một yếu tố nữa, đó là tính năng đóng gói Encapsulation
và mức độ hiển thị của các thành phần package members
và class members
đối với code tham chiếu.
> javac @src.txt
./app/Main.java:3: error: Person is not public in app.data; cannot be accessed from outside package
import app.data.Person; ^
./app/Main.java:9: error: Person is not public in app.data; cannot be accessed from outside package Person $me = new Person ("Semi Dev_", 1001); ^
Access Modifiers
Java
có cung cấp một bộ các từ khóa tùy chỉnh mức độ hiển thị để thể hiện chức năng đóng gói Encapsulation
. Các từ khóa này được sử dụng bằng cách gắn làm tiền tố ở phía trước các thành phần package members
và class members
.
Các class
và các interface
mà chúng ta sẽ nói đến ở bài viết sau - được xem là các package members
và được áp dụng hai mức độ hiển thị đối với code tham chiếu là:
default
- chỉ khả dụng đối với không gian bên trongpackgage
. Đây là cấp độ mặc định và chúng ta có thể viết từ khóadefault
ở phía trước từ khóaclass
hoặcinterface
- hoặc không viết cũng được.public
- khả dụng đối với cả code tham chiếu từ bên ngoàipackage
.
Đối với các class members
thì chúng ta lại có thêm hai mức độ hiển thị nữa:
private
- chỉ khả dụng với code định nghĩa bên trong nội bộ củaclass
đó.default
- chỉ khả dụng đối với code tham chiếu bên trongpackgage
.protected
- khả dụng với code tham chiếu bên trongpackage
và cácclass
kế thừa ở bên ngoàipackage
.public
- khả dụng đối với code tham chiếu từ bất kỳ đâu.
Như vậy, để code ví dụ ở phần trước có thể vận hành được thì chúng ta cần thêm từ khóa public
vào phía trước từ khóa class
để bắt đầu định nghĩa class Person
và các thành phần bên trong class Person
:
package app.data; public class Person { public String name = ""; public int age = 0; public Person (String $name, int $age) { this.name = $name; this.age = $age; } } // -- end class
Extends Visibility
Khi nhắc tới các từ khóa quy định mức hiển thị access modifiers
thì chúng ta còn một trường hợp phải lưu ý đó là thao tác override
khi viết các class
kế thừa.
Ở đây để thể hiện tính năng kế thừa Inheritance
thì Java
đã sử dụng từ khóa extends
- có nghĩa là "mở rộng" tính năng của class
ban đầu. Vì vậy nên khi override
lại bất kỳ class member
nào thì chúng ta cũng chỉ có thể duy trì mức hiển thị đã có, hoặc phải mở rộng hơn (ví dụ private -> protected
), chứ chắc chắn là không thể giới hạn nhỏ lại (ví dụ public -> default
).
(chưa đăng tải) [Object-Oriented + Java] Bài viết #4 - Abstract Class & Interface