Java Bài 15: Tổng Quan Lập Trình Hướng Đối Tượng

Posted by

Được chỉnh sửa ngày 22/3/2017.

Chào mừng các bạn quay trở lại với bài học thứ 15 trong chương trình học Java của Yellow Code Books.

Mình cảm nhận như thời gian vừa qua rất là dài khi mà chúng ta từng bước làm quen với ngôn ngữ Java một cách… không Hướng tối tượng gì ráo. Như các bạn cũng đã biết, ngay từ những bài học Java đầu tiên, mình cũng có nói rằng ngôn ngữ này được sinh ra để chúng ta suy nghĩ theo Hướng đối tượng. Vậy mà chúng ta cũng đã học tập một cách trôi chảy theo lối suy nghĩ cũ rồi đấy thôi, mặc dù thỉnh thoảng chúng ta vẫn xen vào đâu đó vài kiến thức Hướng đối tượng. Điều này chứng tỏ rằng Hướng đối tượng là cái gì đó rất gần gũi và dễ dàng tiếp cận.

Vậy thì Hướng đối tượng là gì? Suy nghĩ theo Hướng cũ và suy nghĩ theo Hướng đối tượng khác nhau như thế nào, chúng có bổ trợ cho nhau không? Tại sao lại phải Hướng đối tượng? Vân vân và mây mây… Tất cả những câu hỏi này sẽ được làm sáng tỏ dần trong loạt bài tiếp theo của Yellow Code Books nhé. Còn bài hôm nay, do chúng ta mới đặt chân vào ngưỡng cửa của Hướng đối tượng, sẽ rất tốt khi cùng nhau dạo qua các khái niệm và các so sánh trước khi đi vào từng bài học cụ thể.

Các Hướng Tư Duy Trong Lập Trình

Lập trình Hướng-đối-tượng hay Hướng-cái-gì đi nữa thì cũng chỉ là một giải pháp, một tư duy trong lập trình mà thôi. Nó không cao siêu hay phức tạp gì. Nó cũng không phụ thuộc vào ngôn ngữ lập trình Java hay gì cả. Nó chỉ là tập hợp các phương pháp và nguyên tắc để giúp bạn suy nghĩ và tổ chức vấn đề, từ đó giúp làm ra một chương trình phức tạp và to lớn một cách dễ dàng hơn.

Và dĩ nhiên với việc suy nghĩ theo một Hướng lập trình nào đó, thì ngôn ngữ lập trình cũng phải hỗ trợ lập trình viên các cú pháp theo các nguyên tắc Hướng đó. Chính vì vậy chúng ta mới có các ngôn ngữ lập trình Hướng đối tượng hay Không hướng đối tượng. Như ngôn ngữ Java mà các bạn đang tìm hiểu là một ngôn ngữ Hướng đối tượng.

Có thể nói là có rất nhiều tài liệu đã mô tả cụ thể về thế nào là lập trình theo Hướng đối tượng và thế nào là lập trình Không theo Hướng đối tượng. Nhưng với một vài tài liệu mà mình biết, chắc chắn là rất khó để các bạn hiểu sự khác nhau này. Vậy với các bài học của mình thì mình mời các bạn tiếp cận các Hướng lập trình theo một cách hoàn toàn khác, đó là, chúng ta hãy cùng xem qua một ví dụ đơn giản, và cùng nhau thay đổi tư duy dần dần để từng bước khám phá cách thức xây dựng một ứng dụng theo Hướng “cũ”Hướng đối tượng sẽ ra sao nhé.

Xây Dựng Ứng Dụng Theo Hướng “Cũ”

Giả sử có yêu cầu rằng bạn hãy viết một chương trình kêu người dùng nhập vào Bán kính của một Hình tròn, sau đó chương trình sẽ in ra console Chu vi và Diện tích của Hình tròn đó.

Nếu bạn bắt tay vào code nhanh sườn của chương trình, thì nó sẽ trông như thế này.

// Kêu người dùng nhập vào Bán kính Hình tròn
System.out.println("Hãy nhập vào Bán kính Hình tròn: ");
Scanner scanner = new Scanner(System.in);
float r = scanner.nextFloat();

// Tính Chu vi Hình tròn ở đây
// ...

// Tính Diện tích Hình tròn ở đây
// ...

// Xuất kết quả Chu vi và Diện tích của Hình tròn ra console
System.out.println("Chu vi Hình tròn: ");
System.out.println("Diện tích Hình tròn: ");

Với cách tiếp cận từ Bài học số 1 đến giờ, rất dễ để bạn bắt tay vào hoàn thành chương trình này đúng không nào. Để tính Chu vi và Diện tích của Hình tròn, chúng ta chỉ cần áp dụng kiến thức toán học vào mà thôi, bạn xem code hoàn chỉnh như sau.

// Khai báo số PI là hằng số
final float PI = 3.14f;

// Kêu người dùng nhập vào Bán kính Hình tròn
System.out.println("Hãy nhập vào Bán kính Hình tròn: ");
Scanner scanner = new Scanner(System.in);
float r = scanner.nextFloat();

// Tính Chu vi Hình tròn ở đây
float cv = 2*PI*r;

// Tính Diện tích Hình tròn ở đây
float dt = PI*r*r;

// Xuất kết quả Chu vi và Diện tích của Hình tròn ra console
System.out.println("Chu vi Hình tròn: " + cv);
System.out.println("Diện tích Hình tròn: " + dt);

Ôi có khó gì đâu! Vậy thì cách tư duy như chúng ta làm với ví dụ này người ta gọi là tư duy theo Hướng thủ tục (POP – Procedure Oriented Programming), hay có thể gọi là Hướng cấu trúc. Bởi vì chúng ta tư duy theo kiểu chia nhỏ yêu cầu ra thành các “thủ tục”, các thủ tục ở đây là các hành động có thể có của một chương trình. Chẳng hạn như với ví dụ trên chúng ta có các thủ tục tính Chu vi Hình tròn, tính Diện tích Hình tròn. Bạn cũng có thể tách từng thủ tục này thành các Hàm (chúng ta sẽ học đến hàm sau) cho chương trình dễ nhìn hơn.

Câu chuyện chưa dừng lại ở đây. Giả sử yêu cầu được nâng tầm lên. Đòi hỏi chương trình in ra thêm Thể tích Hình trụ (Hình trụ này có Bán kính mặt tròn bằng với Bán kính Hình tròn trên kia).

Từ yêu cầu mở rộng này thì chúng ta không cần kêu người dùng nhập vào bán kính nào khác, chỉ cần nhập thêm chiều cao. Vậy là với tư duy Hướng thủ tục, bạn cũng sẽ kêu dễ, và… Boom! Code mới ra đời với một số thủ tục mới.

// Khai báo số PI là hằng số
final float PI = 3.14f;

// Kêu người dùng nhập vào Bán kính Hình tròn
System.out.println("Hãy nhập vào Bán kính Hình tròn: ");
Scanner scanner = new Scanner(System.in);
float r = scanner.nextFloat();

// Kêu người dùng nhập vào Chiều cao Hình trụ
System.out.println("Hãy nhập vào Chiều cao Hình trụ: ");
float h = scanner.nextFloat();

// Tính Chu vi Hình tròn ở đây
float cv = 2*PI*r;

// Tính Diện tích Hình tròn ở đây
float dt = PI*r*r;

// Tính Thể tích Hình trụ ở đây
float ttHinhTru = dt*h;

// Xuất kết quả Chu vi và Diện tích của Hình tròn, Thể tích Hình trụ ra console
System.out.println("Chu vi Hình tròn: " + cv);
System.out.println("Diện tích Hình tròn: " + dt);
System.out.println("Thể tích Hình trụ: " + ttHinhTru);

Cũng may là các hàm tính Chu vi, Diện tích, Thể tích trong ví dụ này rất ngắn. Nhưng bạn có thể thấy nếu yêu cầu ngày một phát sinh, như đòi hỏi tính thêm Chu vi hay Diện tích hay Thể tích cho các Hình vuông, Hình bình hành, Hình cầu,… thì các thủ tục trong chương trình của bạn sẽ phình ra đến mức nào, làm cho chương trình càng khó quản lý nữa. Do đó cần phải có một kiểu tư duy mới khiến cho việc quản lý code được dễ dàng hơn, thậm chí có thể rút ngắn thời gian code thông qua việc tận dụng lại các thủ tục tính toán nữa. Vậy là từ mong muốn đó, tư duy Hướng đối tượng ra đời.

Có nhiều tài liệu cho rằng, phương thức suy nghĩ theo tư duy Hướng thủ tục này là tư duy kiểu top-down, tức là theo kiểu từ trên-xuống, hay còn có thể hiểu là tư duy theo kiểu tổng quát đến cụ thể. Vậy là sao? Tức là bạn sẽ nhìn tổng thể yêu cầu của chương trình trước, như ví dụ bạn thấy ngay yêu cầu là tính Chu vi và Diện tích hình tròn, bạn sẽ xây dựng các thủ tục tính toán đó trước. Sau khi tiếp cận cái tổng thể đó, thì bạn thấy cần phải viết thêm các thủ tục nhỏ hơn để mà dễ quản lý, chẳng hạn bạn muốn thêm các thủ tục tính Bình phương, Thập phương của một số hạng. Nếu còn có thể phân chia thủ tục nhỏ đó thành các thủ tục nhỏ hơn nữa thì cứ phân chia. Đó chính là tư duy kiểu top-down.

Xây Dựng Ứng Dụng Theo Hướng Đối Tượng

Hướng đối tượng (OOP – Object Oriented Programming). Cách tư duy mới này sẽ không hướng đến các thủ tục nữa, mà là hướng đến các đối tượng. Ngoài thực tế thì các đối tượng sẽ là các thực thể hay sự vật mà chúng ta có thể cầm nắm, có thể gọi tên được. Nói chung là có trạng thái và hành vi. Áp dụng vào trong chương trình phần mềm thì khái niệm đối tượng vẫn y như vậy.

Chẳng hạn với ví dụ viết chương trình tính Chu vi và Diện tích Hình tròn trên đây. Thì đối tượng mà ta cần quan tâm đó chính là Hình tròn. Vậy làm sao để giải quyết yêu cầu? Như bạn đã biết, đối tượng được sinh ra trong lập trình (hay ngoài đời thực) đều có những trạng thái và hành vi (hành động) nhất định, ở đây Hình tròn phải có trách nhiệm tính Chu vi và Diện tích của bản thân mình. Tức là các thủ tục ở tư duy Hướng thủ tục trên sẽ được gán vào hết cho Hình tròn xử lý. Thậm chí bạn có thể xây dựng cho Hình tròn tự nó kêu người dùng nhập vào Bán kính và lưu lại. Rồi kêu Hình tròn tự nó in kết quả Chu vi và Diện tích ra console luôn. Khỏe!!! Như mình minh họa bằng code dưới đây, bạn không cần phải biết chính xác code này là như nào đâu, chỉ cần biết ý tưởng của Hướng đối tượng như thế nào là được.

// 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 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();

Bạn có nhận ra sự gọn gàng và dễ quản lý trong code không? Mình rất thích nhìn thấy code như thế này.

Khác biệt sẽ rất lớn khi mà các thủ tục tính Chu vi, tính Diện tích là các thủ tục lớn và phức tạp. Khi đó các thủ tục của Đối tượng nào sẽ được giao cho Đối tượng đó, tức là bạn xây dựng các thủ tục đặc thù đó bên trong các Đối tượng (bạn sẽ được biết cách xây dựng này sau), và khi cần đến các thủ tục nào, chúng ta chỉ cần gọi đến thủ tục thông qua đối tượng đã được khai báo, như đối tượng HinhTron trên đây.

Với việc bạn chỉ định Hình tròn phải có các thủ tục của nó. Thì việc thêm vào một Hình trụ cũng chỉ là việc khai báo thêm một đối tượng mới, với các thủ tục mới tương xứng. Ngoài ra thì đối tượng Hình trụ còn có các đặc tính và thủ tục giống như Hình tròn, do đó chúng ta hoàn toàn có thể dùng lại được các thủ tục đã khai báo bên Hình tròn. Người ta gọi việc dùng lại các thủ tục này là tính Kế thừa trong Hướng đối tượng, thông qua việc chỉ định Hình trụ là con của Hình tròn (chúng ta sẽ xem xét mối quan hệ Kế thừa này ở các bài học sau). Việc Hình trụ là con Hình tròn khiến nó có được các hàm mà cha nó là Hình tròn đã định nghĩa, nên việc quản lý và sử dụng lại code rất dễ dàng. Về sau nếu như xuất hiện thêm Hình cầu, Hình abc, hay Hình xyz gì đó, thì chúng ta hoàn toàn có thể tạo các đối tượng và chúng sẽ có mối quan hệ nào đó với nhau, kèm các thủ tục đặc trưng hay kế thừa của nhau.

Mình cũng ví dụ bằng code cho mong muốn được tính Thể tích Hình trụ như sau.

// Khai báo Đối tượng Hình tròn và Hình trụ
// Và ra lệnh cho đối tượng này thực hiện
// các yêu cầu
HinhTron hinhTron = new HinhTron();
HinhTru hinhTru = new HinhTru();

// Hình tròn và Hình trụ tự kêu người dùng nhập Bán kính
hinhTron.nhapBanKinh();
hinhTru.nhapBanKinh(hinhTron.r);
hinhTru.nhapChieuCao();

// 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ụ tự nó biết cách tính Thể tích
hinhTru.tinhTheTich();

// Hình tròn và Hình trụ tự in kết quả ra console
hinhTron.inChuVi();
hinhTron.inDienTich();
hinhTru.inTheTich();

Nếu Hướng thủ tục trên kia là tư duy theo kiểu top-bottom. Thì việc Hướng đối tượng này, với tiếp cận đầu tiên đến từng Đối tượng như Hình tròn, Hình trụ như ví dụ trên, sau đó ta mới xây dựng các thủ tục cho nó, thêm các mối quan hệ, chỉnh sửa các vai trò cho từng đối tượng khi mà yêu cầu hệ thống càng ngày càng phức tạp. Cách suy nghĩ này người ta gọi là tư duy theo bottom-up, tức là theo kiểu từ dưới lên, hay là từ cụ thể đến tổng quát.

Vậy thôi! Tư duy theo Hướng đối tượng cốt lõi là thế thôi. Bạn đã thấy thích lập trình theo Hướng đối tượng rồi đúng không nào. Không thích cũng phải thích nhé, vì nếu không có Hướng đối tượng, thì các ứng dụng lớn sau này bạn không thể xây dựng nổi đâu. Trên đây chỉ là ví dụ vắn tắt về Hướng đối tượng thôi, mọi thứ râu ria và thế mạnh của nó chúng ta sẽ dần dần nói đến ở các bài học sau nữa nhé.

Vậy Tóm Lại, Tư Duy Theo Hướng Đối Tượng Là Như Thế Nào?

Như bạn đã làm quen trên đây, mục này mình chốt lại thôi. Đó là, đã gọi là Hướng đối tượng, tức là mong muốn bạn luôn suy nghĩ mọi thứ theo đối tượng.

Chẳng hạn với yêu cầu xây dựng phần mềm quản lý Sinh viên, thì Trường học, Lớp học, Sinh viên, Giáo viên, thậm chí Bàn ghế, Máy chiếu, Môn học,… đều có thể trở thành đối tượng để chúng ta vận dụng trong việc quản lý. Miễn là đối tượng đó có xuất hiện bên trong ứng dụng của chúng ta.

Hay với yêu cầu xây dựng phần mềm quản lý Tour (như TourNote bên bài học Android), thì Ghi chú, Chủ đề, Tài khoản, Hành trình,… đều là các đối tượng mà bạn có thể tổ chức.

Bài học hôm nay chỉ dừng lại ở chỗ điểm qua các cách tư duy, giúp bạn có trong đầu một ý niệm về các Hướng trong lập trình. Để rồi các bài học sau chúng ta từng bước làm cụ thể các ý niệm này lên thành một kiến thức hoàn chỉnh. Có một điều cuối cùng mình cần lưu ý là, lập trình Hướng đối tượng không phải một kiểu lập trình mới hoàn toàn giúp thay thế cho Hướng thủ tục ngày xưa. Mà Hướng đối tượng ra đời nhằm mang lại cho bạn một công cụ mới để xây dựng ứng dụng được nhanh hơn. Bạn buộc phải sử dụng Hướng đối tượng để xây dựng sản phẩm, nhưng bạn không buộc phải từ bỏ tư duy Hướng thủ tục. Bên trong Hướng đối tượngHướng thủ tục, tất cả chúng góp phần tạo thành một chương trình hoàn chỉnh có cấu trúc chặt chẽ, dễ đọc, dễ bảo trì, dễ nâng cấp.

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy đánh giá 5 sao nếu thấy thích bài viết, hãy comment bên dưới nếu có thắc mắc, hãy để lại địa chỉ email của bạn để nhận được thông báo mới nhất khi có bài viết mới, và nhớ chia sẻ các bài viết của Yellow Code Books đến nhiều người khác nữa nhé.

Bài Kế Tiếp

Chúng ta sẽ cùng nói đến hai khái niệm cơ bản nhất trong lập trình Hướng đối tượng, đó là Class và Object.

Advertisements
Rating: 4.9/5. From 26 votes.
Please wait...

One comment

Gửi phản hồi