Được chỉnh sửa ngày 26/12/2022.
Chào mừng các bạn đến với bài học Java số 16, bài học về Đối tượng và 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.
Với bài học hôm trước, chúng ta đã làm quen với khái niệm cơ bản về lập trình hướng đối tượng. Khi đó chúng ta đã tiếp cận với việc thay đổi cách tư duy từ hướng thủ tục cũ, sang hướng đối tượng mới mẻ này. Và chắc chắn bạn đã nắm được điều cốt lõi trong tư duy hướng đối tượng này, đó là luôn luôn lấy đối tượng làm trọng tâm.
Vậy bài học hôm nay chúng ta sẽ cùng nhau đi sâu vào tìm hiểu cái trọng tâm đó, đối tượng. Và đã nói đến đối tượng thì cũng phải nói đến lớp.
Đối Tượng (Object)
Như bạn cũng đã biết ở bài học khởi đầu hôm trước, đối tượng là các thực thể hay sự vật mà chúng ta có thể cầm nắm, hoặc có thể gọi tên được. Nghe thì có vẻ lan man, nhưng thực chất là… lan man thật. Mình nói đùa thôi, thực chất là vì hướng đối tượng cũng là một cách tư duy mở. Tức là tùy quan niệm của bạn muốn quản lý đến đối tượng nào mà thôi.
Ví dụ như với phần mềm quản lý việc kinh doanh xe hơi. Thì bạn chọn Xe hơi là một đối tượng để quản lý. Nhưng mình nói rằng Khách hàng cũng là một đối tượng. Và Hóa đơn cũng là một đối tượng nữa. Đấy, tất cả những gì xuất hiện trong một ứng dụng, mà bạn muốn chúng là một thực thể để quản lý, thì bạn cứ xem nó là một đối tượng thôi.
Ngoài ra thì nếu bạn đã chọn thực thể nào đó là đối tượng, thì đối tượng đó ắt hẳn phải có các trạng thái và hành vi.
Trạng Thái Của Đối Tượng
Trạng thái của đối tượng nói lên các đặc điểm của đối tượng đó.
Ví dụ, khi bạn “nắm” lấy một đối tượng Xe hơi trong ứng dụng quản lý xe hơi trên đây để xem, thì sẽ thấy các trạng thái của nó như: xe này màu xanh, thuộc hãng Ford, 7 chỗ ngồi. Nhưng nếu bạn “cầm” lấy một chiếc xe khác, sẽ thấy các trạng thái khác, như: xe này màu trắng, thuộc hãng Toyota, 4 chỗ ngồi.
Bạn thấy đấy, tư duy trong lập trình theo hướng đối tượng trông rất thực tế đúng không nào. Bạn nhớ các trạng thái này của đối tượng nhé, chúng ta sẽ cần đến nó ở các ví dụ trong các kiến thức tiếp theo bên dưới.
Hành Vi Của Đối Tượng
Khác với trạng thái là các đặc điểm của đối tượng. Thì hành vi chính là các hành động của đối tượng đó, hay có thể hiểu đó là các hành động mà đối tượng đó có trách nhiệm phải thực hiện.
Như bạn đã làm quen với ví dụ mở màn ở bài trước, khi chúng ta dần chuyển các code tính toán ở main() vào cho đối tượng Hình tròn. Thì các hàm tính toán đó trở thành các hành vi của đối tượng Hình tròn này. Điều này có nghĩa là Hình tròn phải có trách nhiệm thực hiện các hành vi tính Chu vi và Diện tích của nó. Và dĩ nhiên Hình tròn không có trách nhiệm phải thực hiện các hành động tính Chu vi và Diện tích Hình vuông, vì các hành vi này sẽ thuộc về sự quản lý của đối tượng Hình vuông. Bạn đã hiểu rõ hơn về hành vi của từng đối tượng rồi đúng không nào.
Lớp (Class)
Nếu bạn đã nắm về khái niệm đối tượng rồi. Thì với khái niệm lớp sẽ đơn giản hơn một tí. Lớp được xem là một khuôn mẫu để tạo ra các đối tượng. Ngắn gọn vậy thôi đó bạn, nhưng ngắn vậy thì chẳng hiểu gì cả. Thực chất không khó lắm đâu, bạn nhất định phải phân biệt giữa lớp và đối tượng. Chúng ta cùng đi từ từ qua các ví dụ sau.
Ví Dụ 1: Làm Bánh
Nào chúng ta hãy quên đi kiến thức lập trình một chút, hãy bắt tay vào làm các bánh quy bơ như sau. Giả sử bạn đã biết hết các công thức làm bánh. Và mình nhờ bạn giúp mình làm ra chúng với hình trái tim như này để mình mang đi tặng “người ấy”.

Nhưng bạn lại nói rằng biết công thức thì chưa đủ. Nếu muốn bạn làm chính xác các bánh có hình thù như vậy, thì hãy đưa bạn cái khuôn. Vâng, thì đây là cái khuôn.

Đó không phải câu chuyện về tặng “người ấy” như thế nào, mà là câu chuyện giữa bánh quy và khuôn. Bạn hãy đến Ví dụ 2 trước khi mình giải thích chúng.
Ví Dụ 2: Thiết Kế Các Mẫu Xe Hơi
Mình muốn các bạn đi lan man một chút qua ví dụ kế tiếp. Giả sử bạn là một họa sĩ 3D, chuyên về vẽ texture hoàn thiện hình ảnh cho xe hơi. Với yêu cầu rằng bạn hãy cho ra thành phẩm là những chiếc xe hơi với các màu như sau.

Ồ tất nhiên bạn sẽ làm được thôi. Nhưng trước hết bạn yêu cầu một bản vẽ concept (hay đại loại một ý tưởng gì đấy) về mẫu xe hơi này, thì bạn mới có thể khoác lên chúng các màu sắc được chứ. Vâng mình cũng đã chuẩn bị cho bạn, bản vẽ concept đây.

Vậy đó là câu chuyện về các thành phẩm bản vẽ xe hơi và bản vẽ concept.
Những ví dụ trên đây mang lại một thông điệp gì. Mình muốn các bạn hình dung từ thực tế rằng, các đối tượng mà chúng ta cần quan tâm đến từ các ví dụ này chính là những thứ hữu hình có thể nhìn thấy hay tương tác được từ phía người dùng. Trong đó thì các thành phẩm bánh quy và bản vẽ xe hơi chính là các đối tượng. Các đối tượng này được tạo ra dựa trên các khuôn mẫu của chúng, chính là cái khuôn bánh và bản vẽ concept, chúng chính là các lớp.
Ví Dụ 3: Làm Phần Mềm Quản Lý Sinh Viên
Giờ thì không ví dụ lan man nữa. Chúng ta quay về lĩnh vực lập trình với ví dụ về quản lý Sinh viên. Giả sử trong ngôi trường mà chúng ta cần quản lý có các Sinh viên sau.

Áp dụng từ các ví dụ 1 và 2. Sinh viên chắc chắn là đối tượng cần quản lý rồi. Vậy đâu sẽ là khuôn mẫu cho các đối tượng Sinh viên này. Trong trường hợp này, cái Khuôn mẫu ấy hơi trừu tượng xíu, nó sẽ là một hình tượng chung chung với các nhãn như: Giới tính, Tên, Lớp, Tuổi, Quê quán, Chiều cao, Cân nặng. Như hình bên dưới.

Từ khái khuôn mẫu đó, hay ta đã biết nó là lớp, nó sẽ giúp tạo ra nhiều đối tượng Sinh viên khác nhau. Như John-Giới tính Nam-22 tuổi-Lớp Java. Hay Elly-Giới tính Nữ-21 tuổi-Lớp Android,…
Vậy bạn đã hiểu khái niệm lớp là một khuôn mẫu để tạo ra các đối tượng rồi đúng không nào. Và nếu như đối tượng có các trạng thái và hành vi, thì lớp cũng có các thuộc tính và phương thức tương ứng.
Khai Báo Lớp
Từ bài hôm trước tới giờ chúng ta chỉ lan man nói và nói. Giờ thì đến lúc code rồi. Nhưng trước khi đi vào cách thức code một Lớp, thì hãy cùng nhau đi qua phần này trước.
Hình Dung Về Lớp
Khi bạn muốn đưa một thực thể nào đó về một đối tượng để quản lý, thì bạn phải tạo khuôn mẫu cho đối tượng đó. Đó chính là lớp. Và trước khi bắt tay vào tạo một lớp, bạn phải hình dung lớp đó với ba thành phần chính như biểu diễn sau.

Khai Báo Lớp
Một khi bạn đã hình dung ra một lớp với ba thành phần như trên, thì việc biểu diễn ra thành code Java sẽ theo cú pháp sau.
class tên_lớp { các_thuộc_tính; các_phương_thức; }
Trong đó:
- class là một keyword cho biết bạn đang khai báo một lớp.
- tên_lớp là tên định danh cho lớp đó, quy luật đặt tên cho lớp cũng giống như quy luật đặt tên cho Biến. Nhưng bạn lưu ý một tí là tên_lớp này nên viết in hoa hết từng chữ đầu của mỗi từ nhé, ví dụ như HinhTron, SinhVien, HoaDon,… để mà phân biệt với tên của đối tượng sẽ được nói ở phần dưới đây.
- các_thuộc_tính và các_phương_thức mình cũng đã nhắc đến trên đây rồi. Nhưng các bài sau mình sẽ nói rõ hơn các định nghĩa này.
Bài Thực Hành Số 1
Bài thực hành này chúng ta sẽ tiến hành xây dựng lớp Hình tròn mà ở bài hôm trước mình có ví dụ cho các bạn xem.
Bài thực hành này không đòi hỏi các bạn phải hiểu hết tất cả các dòng code, các bạn chỉ cần nhìn vào cấu trúc tổng quát của lớp Hình tròn như những gì mình nói đến ở bài hôm nay. Tất cả những chi tiết đắt giá của lớp sẽ được mình nói tiếp ở các bài học sau.
Chúng ta tạm thời code vào chung với lớp đang chứa đựng main(), và bên dưới main() này bạn khai báo HinhTron như sau.
public class MyFirstClass { public static void main(String[] args) { } // Khai báo một Lớp Hình tròn class HinhTron { // Dưới đây là các Thuộc tính final float PI = 3.14f; float r; float cv; float dt; // Dưới đây là các Phương thức void nhapBanKinh() { System.out.println("Hãy nhập vào Bán kính Hình tròn: "); Scanner scanner = new Scanner(System.in); r = scanner.nextFloat(); } void tinhChuVi() { cv = 2 * PI * r; } void tinhDienTich() { dt = PI * r * r; } void inChuVi() { System.out.println("Chu vi Hình tròn: " + cv); } void inDienTich() { System.out.println("Diện tích Hình tròn: " + dt); } } }
Mình nói thêm một chút. Với khai báo một lớp như trên thì:
- tên_lớp lúc này chính là HinhTron.
- các_thuộc_tính bao gồm PI, r, cv, dt.
- các_phương_thức bao gồm nhapBanKinh(), tinhChuVi(), tinhDienTich(), inChuVi(), inDienTich().
Khai Báo Và Khởi Tạo Đối Tượng
Khai Báo Đối Tượng
Bạn đã biết lớp chính là khuôn mẫu để tạo nên đối tượng. Và Bài thực hành số 1 trên kia bạn cũng đã tạo ra một lớp HinhTron. Vậy thì từ lớp HinhTron này bạn hoàn toàn có thể tạo ra các đối tượng khác nhau như sau.
HinhTron hinhTron1; HinhTron hinhTron2; HinhTron hinhTron3; ... HinhTron hinhTronX;
Ồ, hẳn bạn có ngay so sánh, khi chúng ta làm quen đến biến, chúng ta cũng có các khai báo tương tự với các kiểu dữ liệu nguyên thủy.
int count; int index; boolean result;
Vậy thì khai báo một biến kiểu đối tượng và khai báo một biến kiểu nguyên thủy có khác nhau hay không. Câu trả lời là có, thậm chí chúng còn có một sự khác biệt lớn.
Với kiểu dữ liệu nguyên thủy, như bạn cũng đã biết, khi bạn khai báo một biến, giá trị của biến được lưu trữ vào trong chính biến đó, bạn hãy tưởng tượng việc lưu trữ này được mô tả theo sơ đồ như sau.

Sơ đồ thể hiện giá trị mặc định của kiểu số là 0 và boolean là false. Nếu chúng ta gán giá trị khác vào biến thì chúng ta vẫn hiểu là giá trị đó cũng được lưu vào biến như sơ đồ trên.
Nhưng khi bạn khai báo các đối tượng của lớp, hệ thống không tạo ra một biến có chứa giá trị là một đối tượng, mà sẽ tạo ra một tham chiếu đến đối tượng cụ thể. Như các code trên đây khi tạo các đối tượng hình tròn sẽ được minh họa như sau.

Giá trị null trong sơ đồ trên biểu thị rằng các đối tượng hinhTron1, hinhTron2,… tuy có kiểu dữ liệu là HinhTron, nhưng hiện tại các đối tượng này đang mang giá trị là các tham chiếu, mà các tham chiếu này không trỏ đến bất kỳ đối tượng nào (hay hiểu tham chiếu không có giá trị), nên được gán bằng giá trị null. Chúng ta sẽ nói rõ về giá trị null sau, nhưng bạn cũng nên biết rằng, với tham chiếu là null, các đối tượng chúng ta tạo ra chưa sử dụng được.
Ví dụ bạn code như sau sẽ bị báo lỗi.
HinhTron hinhTron1; hinhTron1.nhapBanKinh();
Chúng ta hãy đến bước tiếp theo để có thể sử dụng các kiểu đối tượng đã khai báo này.
Khởi Tạo Đối Tượng
Đối tượng sẽ được khởi tạo giá trị, hay như biểu đồ trên bạn hiểu là làm cho tham chiếu trỏ đến một giá trị đối tượng cụ thể, bằng cách sử dụng từ khóa new
, kèm với phương thức khởi tạo (constructor) của lớp mà chúng ta sẽ nói ở bài học này sau.
Vậy với các khai báo đối tượng hình tròn ở ví dụ trên chúng ta khởi tạo chúng như sau.
HinhTron hinhTron1 = new HinhTron(); HinhTron hinhTron2 = new HinhTron(); HinhTron hinhTron3 = new HinhTron(); ... HinhTron hinhTronX = new HinhTron();
Code trên sẽ tạo ra các đối tượng hinhTron1, hinhTron2,… được tạo ra từ một khuôn mẫu chính là lớp HinhTron, được mang giá trị chính là các tham chiếu đến các đối tượng cụ thể. Khi đó sơ đồ được hiểu như sau.

Đến đây chắc bạn đã hiểu rõ vấn đề rồi đúng không nào. Giờ thì bạn hãy nhìn lại các code chúng ta đã dùng để khai báo các đối tượng để mà sử dụng từ trước đến giờ xem. Không cần tìm đâu xa, ngay cả trong bài thực hành trên cũng có đấy thôi, chính là dòng khai báo đối tượng scanner từ lớp Scanner (constructor của lớp Scanner có truyền thêm tham số System.in
có hơi khác với constructor của HinhTron chúng ta vừa làm quen, đến bài về constructor bạn sẽ hiểu rõ thôi).
void nhapBanKinh() { System.out.println("Hãy nhập vào Bán kính Hình tròn: "); Scanner scanner = new Scanner(System.in); r = scanner.nextFloat(); }
Bài Thực Hành Số 2
Với lớp HinhTron đã khai báo ở Bài thực hành số 1. Bây giờ bạn hãy thử khai báo và khởi tạo đối tượng Hình tròn bên trong main() như sau.
public static void main(String[] args) { // Khai báo Đối tượng Hình tròn và ra lệnh cho đối tượng này thực hiện // các yêu cầu HinhTron hinhTron = new MyFirstClass().new HinhTron(); // Hình tròn tự kêu người dùng nhập Bán kính hinhTron.nhapBanKinh(); // Hình tròn tự nó biết cách tính Chu vi hinhTron.tinhChuVi(); // Hình tròn tự nó biết cách tính Diện tích hinhTron.tinhDienTich(); // Hình tròn tự in kết quả ra console hinhTron.inChuVi(); hinhTron.inDienTich(); }
Một lần nữa đừng chú trọng quá vào cách thức sử dụng các phương thức trong một đối tượng, bạn sẽ quen với đối tượng sớm thôi.
Bạn chỉ cần chú ý một số chỗ.
- Dòng code
HinhTron hinhTron = new …
chính là nơi bạn khai báo một đối tượng là hinhTron. Đối tượng hinhTron này được tạo ra từ Lớp HinhTron. Như bạn biết rằng bạn có thể tạo ra bao nhiêu đối tượng Hình tròn từ lớp HinhTron đều được cả. Thậm chí bạn có thể tạo ra mảng các đối tượng Hình tròn mà chúng ta sẽ xem xét ở một bài khác.
- Từ khóa new như mình nói là bắt buộc khi khai báo và khởi tạo các kiểu dữ liệu đối tượng này, mục đích là giúp cho đối tượng được khai báo có tham chiếu rõ ràng đến giá trị của đối tượng.
- Các dòng code còn lại là các dòng gọi đến các thuộc tính hay các phương thức của đối tượng đó.
Giờ đây nếu thực thi dòng code này thì bạn đã có thể tương tác với console được rồi đấy nhé.
Kết Luận
Chúng ta có thể kết thúc bài học hôm nay ở đây. Như vậy là các bạn vừa làm quen với hai khái niệm cơ bản nhất trong lập trình Hướng đối tượng, đó là lớp (class) và đối tượng (object). Và cùng nhau định nghĩa và khởi tạo đối tượng hinhTron từ lớp HinhTron để thực hành thử. Chúng ta sẽ nói sâu hơn về cấu trúc và cách sử dụng đối tượng ở các bài học tiếp theo.
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
Chúng ta sẽ nói chi tiết về cách khai báo và sử dụng các thuộc tính và phương thức trong một lớp.
Sao lâu quá không thấy bài 17 ad ơi!
Nhưng trước tiên cũng cảm ơn ad vì đã bỏ công sức, thời gian, và chia sẽ.
Yeah, bài 17 đang soạn nha bạn, sẽ ra sớm thôi 😉
Quá hay, quá dễ hiểu. Đúng là phải biết đơn giản hóa 1 vấn đề phức tạp mới là khó.
Bạn ManhDN phán quá chuẩn. Mình vẫn mong muốn mang đến các bài viết gần gũi, dễ hiểu nhất có thể, giống như cách chúng ta trao đổi kiến thức hằng ngày với nhau í. Nhờ có comment của bạn mà mình biết mình vẫn đi đúng hướng. Hihi.
Sao lại có new MyFirstClass() ở dùng 4 phần thực hành số 2 thế anh ?
Bạn Hiếu để ý khá tốt. Thực ra lớp HinhTron lúc bấy giờ đang là một lớp nằm trong lớp MyFirstClass. Chính vì vậy khi muốn khai báo một hình tròn, thay vì viết thoải mái hinhtron = new HinhTron(), thì hệ thống buộc phải thông qua lớp bao của nó, và thế là phải viết là hinhtron = new FirstClass().new HinhTron(). Khai báo này làm cho các bạn bị rối, nên mình có nói bạn không cần chú ý kỹ code ở phần này quá, đến khi nói về lớp lồng nhau, thì mình sẽ trình bày kỹ hơn trường hợp này.
Cảm ơn anh hihi
Bạn ơi chỗ khai báo một đối tượng hình tròn có bị thiếu không ấy, vì mình gõ vào giống bạn thì bị lỗi. Mò một lát, mình gõ lại như vầy thì được, bạn xem giúp mình với nhé:
MyFirstClass my = new MyFirstClass();
MyFirstClass.Circle circle =my.new Circle();
Hoặc là như vầy:
Circle circle = new MyFirstClass().new Circle();
Chào bạn ikuo. Mình có nêu code ở trong mục “Bài thực hành số 2” là như bạn nói mà:
// Khai báo Đối tượng Hình tròn và ra lệnh cho đối tượng này thực hiện
// các yêu cầu
HinhTron hinhTron = new MyFirstClass(). new HinhTron();
Bạn ikuo thử xem lại coi có đúng không nè.
Mình code thiếu, cảm ơn bạn :>
Cám ơn ad về bài viết rất hay và dễ hiểu. Mình follow FB của ad luôn rồi, ahihi 😀
Cám ơn ad. Bao lâu nay giờ mới thấy được một bài viết dễ hiểu về OOP như này. Đọc xong như ngộ đc đạo 🙂
Cách viết bài của add rất dễ hiểu.
Cảm ơn add vì bài viết (y)