Được chỉnh sửa ngày 29/12/2022.
Chào mừng các bạn đến với bài học Java số 17, bài học về Thuộc tính của Lớp. Bài học này nằm trong chuỗi bài học lập trình ngôn ngữ Java của Yellow Code Books.
Chúng ta đã cùng nhau đi qua các bài giới thiệu về lập trình hướng đối tượng, và chắc chắn các bạn cũng đã hiểu rõ thế nào là Đối tượng và thế nào là Lớp rồi phải không. Chúng ta sẽ còn nhiều bài học và bài tập thú vị liên quan đến các kiến thức hướng đối tượng này ở phía trước, và tất cả chúng đều xoay quanh hai khái niệm trọng tâm, đó là đối tượng và lớp.
Từ bài học hôm nay chúng ta sẽ bắt đầu đi chi tiết vào từng khái niệm và cách sử dụng của các thành phần bên trong một lớp. Và mình đã rất mong muốn nói hết kiến thức về thuộc tính và phương thức của một lớp ở trong bài học hôm nay. Tuy nhiên, trong khi từ từ diễn đạt các vấn đề liên quan đến thuộc tính trước, mình mới ngỡ ra là có rất nhiều thứ để nói về nó. Thế là mình chỉ đủ “giấy mực” để nói đến thuộc tính mà thôi, hẹn các bạn bài sau sẽ là sân khấu cho phương thức nhé.
Trước khi đi vào chi tiết về thuộc tính, chúng ta hãy cùng nhau tạo một project mới.
Thực Hành Tạo Một Project Mới
Chắc chắn bạn có thắc mắc, rằng bài hôm trước chúng ta đã thực hành việc khai báo một lớp rồi, sao không dùng lớp đó mà học tiếp cho bài hôm nay. Tuy nhiên, mình cũng muốn nói rằng, hôm trước bạn đã thử tạo lớp HinhTron cùng cấp với main(), mà như bạn đã biết thì main() này lại đang nằm trong một lớp khác, cụ thể lớp này có tên MyFirstClass mà chúng ta đã tạo từ thuở nảo thuở nào, từ bài học số 3 lận, hi vọng bạn còn nhớ.
Như vậy túm lại là lớp HinhTron mà bạn đã tạo từ bài trước đang nằm trong lớp MyFirstClass, điều này bạn chưa được tiếp cận, nó liên quan đến kiến thức lớp lồng (inner class hay nested class) mà chúng ta sẽ nói đến sau. Để hỗ trợ tốt việc quản lý lớp bên trong các ứng dụng, InteliJ hay các IDE khác đều hỗ trợ bạn tạo nhiều lớp khác nhau mà mỗi lớp như vậy sẽ tách biệt nhau bởi một file .java. Và bài thực hành hôm nay chúng ta sẽ bắt đầu làm quen với việc quản lý các lớp một cách tách biệt như vậy.
Tạo Project Mới
Bạn hãy xem lại mục này của bài 3 để biết cách tạo mới một project và tạo các class với InteliJ nhé. Sau đó hãy tự tạo một project mới có tên OOPLearning. Rồi cũng hãy tự tạo lớp MainClass. Đảm bảo có phương thức main() bên trong lớp MainClass. Lớp HinhTron thì sẽ được tạo ở mục thực hành kế tiếp bên dưới.
Hình ảnh của project mới, lớp MainClass.java và code của main() được diễn tả bằng hình sau.

Như bạn biết, một lớp sẽ bao gồm các thuộc tính và phương thức. Và như mình nói đó, do không đủ giấy mực để nói hết hai thành phần này trong bài hôm nay, nên mình sẽ nói các vấn đề liên quan đến khai báo và sử dụng thuộc tính trước.

Thuộc Tính Của Lớp
Thuộc tính hay còn gọi là field. Như bạn đã biết, các thuộc tính của lớp sẽ giúp tạo ra các trạng thái, hay các đặc điểm của các đối tượng được tạo ra từ lớp này.
Để khai báo một thuộc tính thì chúng ta có cú pháp sau.
[khả_năng_truy_cập] kiểu_thuộc_tính tên_thuộc_tính [= giá_trị_ban_đầu];
Ngoại trừ khả_năng_truy_cập sẽ được nói đến ở bài học sau (vì thành phần này nằm trong cặp ngoặc vuông, có nghĩa là có khai báo nó hay không thì cũng sẽ không bị hệ thống báo lỗi, do đó hôm nay mình sẽ chưa nói đến nó). Thì các thành phần còn lại bạn khai báo hoàn toàn giống với cách khai báo một biến (hay hằng). Nếu bạn không tin thì có thể xem lại bài viết về biến và hằng nhé.
Thực Hành Tạo Các Thuộc Tính
Chúng ta tiếp tục tạo mới lớp HinhTron như ở bài thực hành hôm trước. Tuy nhiên ở bài này bạn hãy thực hành việc tạo một lớp tách biệt ra với lớp MainClass.
Tạo Mới Lớp HinhTron
Chi tiết lớp HinhTron này khi tạo xong sẽ như hình bên dưới đây.

Thêm Thuộc Tính Vào Lớp HinhTron
Bạn hãy thêm các thuộc tính sau vào lớp HinhTron vừa mới tạo.

Code của nó như sau.
public class HinhTron { final float PI = 3.14f; float r; float cv; float dt; }
Mọi thứ đều như bài học hôm trước. Tuy nhiên với bài hôm nay bạn đã hiểu hơn về quy tắc khai báo các thuộc tính đúng không nào.
Mối Liên Hệ Giữa Thuộc Tính Và Biến
Qua bài thực hành trên thì bạn có thể thấy rằng các thuộc tính mà bạn khai báo bên trong một lớp, chúng không khác gì so với các biến bên trong một phương thức (chẳng hạn như trong phương thức main() mà bạn đã làm quen từ các bài trước) đúng không nào.
Tuy nhiên thuộc tính là thuộc tính, và biến là biến. Chúng không phải là một. Có vài tài liệu gọi rõ ra biến với cái tên là biến local, hay biến cục bộ (local variable). Để giúp phân biệt rõ hơn với từ thuộc tính, còn được gọi là thuộc tính global, hay thuộc tính toàn cục (global field). Vậy mục này mình sẽ giúp các bạn nắm rõ hơn về thuộc tính thông qua các mối liên hệ giữa thuộc tính của lớp và biến của phương thức nhé.
Mối Liên Hệ Thứ Nhất
Khai báo chúng rất giống nhau. Như mình có trình bày trên kia, ngoại trừ khả_năng_truy_cập sẽ được nói ở bài sau ra, thì khai báo của chúng được khai báo với một nguyên tắc như nhau.
public class HinhTron { /** * Demo sự giống nhau giữa Thuộc tính và Biến * nếu như không có thành phần khả_năng_truy_cập trước * các thuộc tính */ // Thuộc tính final float PI = 3.14f; float r; float cv; float dt; void tinhChuVi() { // Biến float banKinh = 10; cv = 2 * PI * banKinh; } }
Mối Liên Hệ Thứ Hai
Biến chỉ được sử dụng cục bộ bên trong khối lệnh của phương thức, trong khi thuộc tính được sử dụng toàn cục.
Và bởi vì biến chỉ được sử dụng cục bộ bên trong khối lệnh của phương thức, nên khi một phương thức thực thi hết các dòng code của nó, thì biến này cũng sẽ bị xóa khỏi bộ nhớ. Như vậy biến bên trong phương thức chỉ dùng để tính toán tạm mà thôi.
Còn thuộc tính thì được dùng toàn cục, nên khi một phương thức kết thúc, thuộc tính này vẫn sẽ được lưu giữ giá trị cuối cùng của nó. Như ví dụ bên dưới, thuộc tính r sẽ được mang giá trị là 10 sau khi bạn gọi đến tinhDienTich(). Điều này cũng đã được bạn kiểm chứng từ thực hành của bài trước, khi mà bạn gọi liên tiếp các phương thức hinhTron.nhapBanKinh() rồi hinhTron.tinhChuVi(),… hinhTron.inChuVi().
public class HinhTron { /** * Demo cách sử dụng toàn cục của thuộc tính, * và cách sử dụng cục bộ của biến */ // Thuộc tính final float PI = 3.14f; float r; float cv; float dt; void tinhChuVi() { // Biến banKinh định nghĩa ở đây chỉ dược sử // dụng cục bộ trong phương thức này float banKinh = 10; cv = 2 * PI * banKinh; } void tinhDienTich() { // r là thuộc tính của lớp, được sử dụng thoải mái // trong các phương thức r = 10; // Dĩ nhiên dt và PI cũng là thuộc tính toàn cục dt = PI * r * r; } }
Mối Liên Hệ Thứ Ba
Chuyện gì xảy ra nếu bạn định nghĩa một biến có cùng tên với một thuộc tính?
Khi này hệ thống sẽ giúp bạn xác định đâu là biến cục bộ, còn đâu là thuộc tính toàn cục. Bạn có thể xem ví dụ sau. Khi biến r được khai báo bên trong phương thức, dù trùng tên với thuộc tính r, nhưng r trong tinhChuVi() vẫn được hiểu là biến cục bộ đấy nhé.
public class HinhTron { /** * Demo khi một biến trong một phương thức trùng tên * với một thuộc tính trong một lớp */ // Thuộc tính final float PI = 3.14f; float r; float cv; float dt; void tinhChuVi() { // Biến r này là biến cục bộ, vì nó được // khai báo lại, dù cho nó trùng tên float r = 10; cv = 2 * PI * r; } void tinhDienTich() { // Thuộc tính r này là toàn cục r = 15; dt = PI * r * r; } }
Cũng ở mối liên hệ này, mình cũng muốn nói đến một vấn đề nhỏ nữa. Đó là nhiều khả năng sau này trong một phương thức, bạn đã khai báo một biến trùng tên với thuộc tính của lớp rồi, nhưng… trớ trêu thay bạn vẫn sẽ muốn lúc thì dùng biến, lúc thì dùng thuộc tính với cùng một tên ấy. Để giải quyết tình trạng này, Java có hỗ trợ từ khóa this. this có ý nói: chính là đối tượng này. Đó là lý do vì sao bảng các keyword mà bạn làm quen ở bài 4 ngày xưa có liệt kê từ khóa this vào đó. Bạn xem ví dụ sử dụng this như sau. Cách sử dụng cụ thể của từ khóa this sẽ được mình nói ở bài này.
public class HinhTron { /** * Demo khi một biến trong một phương thức trùng tên * với một thuộc tính trong một lớp. Nhưng chúng ta * có thể dùng từ khóa this để chỉ định đến thuộc tính của lớp. */ // Thuộc tính final float PI = 3.14f; float r; float cv; float dt; void tinhChuVi() { // Biến r cục bộ float r = 10; // this.r lại là thuộc tính, dòng code này // gán giả trị của biến r vào thuộc tính r this.r = r; // r trong phép tính này là biến r cục bộ đấy nhé cv = 2 * PI * r; } }
Truy Xuất Đến Thuộc Tính Của Lớp Từ Bên Ngoài
Khi bạn ở đâu đó bên ngoài một lớp, và muốn truy xuất đến các thuộc tính của lớp đó, như bạn cũng đã biết đâu đó qua các bài thực hành trước, đó là bạn có thể sử dụng toán tử “.”.
Mình ví dụ với lớp HinhTron mà chúng ta đã khai báo ở trên kia, giả sử ở main() khi chúng ta đã khai báo đối tượng hinhTron, chúng ta có thể truy xuất đến các thuộc tính của hinhTron như sau.
public class MainClass { public static void main(String[] args) { HinhTron hinhTron = new HinhTron(); hinhTron.r = 10.0f; } }
Tuy nhiên code trên đây chỉ là một ví dụ về cách truy xuất đến thuộc tính của lớp thôi. Theo nguyên tắc của gói ghém dữ liệu bên trong các lớp của OOP, thì một lớp sẽ không cho phép bên ngoài truy xuất đến các thuộc tính của nó một cách trực tiếp như vậy, bằng việc định nghĩa các khả_năng_truy_cập mà mình đã nói ở trên kia. Và chắc chắn chúng ta sẽ nói đến điều này khi giải thích cụ thể từng khả_năng_truy_cập ở bài sau nhé.
Kết Luận
Chúng ta vừa kết thúc bài học về cách sử dụng các thuộc tính của một lớp. Bài sau mình sẽ nói đến cách sử dụng các phương thức.
Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:
– Đánh giá 5 sao ở mỗi bài viết nếu thấy thích.
– Comment bên dưới mỗi bài viết nếu có thắc mắc.
– Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
– Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.
– Ủng hộ blog theo hướng dẫn ở thanh bên phải để blog ngày càng phát triển hơn.
Bài Kế Tiếp
Bài tiếp theo chúng ta sẽ xem qua tất cả các kiến thức liên quan đến phương thức của lớp, bao gồm các tham số truyền vào, kết quả trả về, truy xuất đến phương thức,…
hay quá mong ad tiếp tục ra các bài viết tiếp theo trong thời gian nhanh nhất. Thanks ad!!
Mình đang soạn bài kế tiếp đây ^^
Đã có quá nhiều bài học java cơ bản, OOP trên mạng và vô số sách. Nhưng chưa có ai viết hay, dễ hiểu, trực quan, cuốn hút như bạn này. Có điều bạn cố gắng ra bài nhanh chút để anh e đỡ phải đợi.
Cảm ơn bạn ManhDN, mình sẽ cố gắng dành thời gian viết nhiều hơn.
Phải nói là loạt bài hướng dẫn của anh rất gần gũi với newbie như em. Rất bổ ích
(like)
anh viết thực sự rất dễ hiểu. Rất đáng đọc
Thực sự rất hay và bổ ích.
Tuyệt vời @@ nhờ anh em hiểu rõ hơn về hướng đối tượng. Cảm ơn anh.
Dạy rất chi tiết và dễ hiểu , ko như các trang khác. Thanks AD nhiều^^
Anh viết rất dễ hiểu và rõ ràng, chúc anh mạnh khoẻ và tiếp tục ra bài mới nha. Mấy bài này trên trường dạy em nỏ hiểu chi cả (❁´◡`❁)
Thực sự câu từ rất gần gũi và dễ hiểu. Cảm ơn tác giả !
Mình muốn xem từ những bài đầu trong “chương trình học java” này . Nhưng mà hình như link bị gỡ rồi hay sao ấy.
Vẩn còn mà bạn, do danh sách bài học nhiều quá nên trang Web có phân trang đấy, bạn để ý cuộn xuống hết danh sách rồi chú ý bên dưới có đánh dấu trang, bạn chọn các trang số lớn nhất để xem các bài đầu tiên nhé.
thật sự cảm ơn tác giả vì nội dung bổ ích và rất dễ hiểu !
rất bổ ích ạ, cảm ơn anh