Nếu bạn chưa biết về lập trình hướng đối tượng (Object Oriented Programming – OOP) thì bạn nên tìm hiểu trước khi học Java, vì Java là một ngôn ngữ rất nặng về hướng đối tượng.
Đối tượng – Object
Đối tượng là khái niệm cốt lõi trong công nghệ hướng đối tượng. Thế giới xung quanh chúng ta tràn ngập các đối tượng: con chó, cái bàn, tivi, xe đạp…
Trong một đối tượng có 2 thành phần chính là trạng thái (state) và hành vi (behavior).
Trạng thái là các thông tin, đặc điểm của đối tượng, chẳng hạn như con chó thì có tên, màu sắc, giống loài…, xe đạp thì có loại bánh xe, loại tay cầm, tốc độ hiện tại…v.v
Hành vi là các hoạt động của đối tượng, chẳng hạn như con chó thì vẫy đuôi, sủa…, xe đạp thì có thể tăng tốc, thắng, quẹo trái phải…v.v
Để có thể thiết kế các trạng thái và hành vi của đối tượng và viết thành code thì bạn cần trả lời 2 câu hỏi, “Đối tượng này có thể có các trạng thái gì?” và “Đối tượng này có thể thực hiện những gì?”. Đôi khi trong quá trình quan sát, bạn có thể nhận thấy cấu trúc của các đối tượng có sự phức tạp rất khác nhau, chẳng hạn như cái đèn thì chỉ có 2 trạng thái là mở và tắt, 2 hành vi là bật đèn và tắt đèn, trong khi cái đài radio thì lại có thể có các trạng thái như mở, tắt, âm lượng, kênh…v.v và các hành vi là mở đài, tắt đài, tăng âm lượng, giảm âm lượng, tìm kiếm, dò sóng…v.v Đôi khi các trạng thái và hành vi này nhiều và phức tạp đến nỗi bạn có thể chuyển nó thành một đối tượng khác, tức là bây giờ đối tượng này chứa một đối tượng khác.
Đối tượng trong lập trình cũng được thiết kế giống với đối tượng ngoài đời thật, nhưng thay vì gọi 2 thành phần là trạng thái và hành vi, thì chúng ta gọi là trường (field) hoặc thuộc tính, biến trong một số ngôn ngữ khác, và phương thức (method) hoặc hàm trong một số ngôn ngữ khác. Phương thức làm công việc tính toán, thay đổi giá trị của các trạng thái, trao đổi thông tin với các đối tượng khác.
Một đặc điểm của lập trình hướng đối tượng là che giấu thông tin, các thông tin về trường/thuộc tính của đối tượng chỉ có thể được biết thông qua việc gọi phương thức/hàm chứ không thể được đọc một cách trực tiếp. Tính năng này cho phép chúng ta bảo vệ dữ liệu của các đối tượng, không để chúng bị điều khiển một cách vô trật tự.
Ví dụ như chúng ta có đối tượng xe đạp có thuộc tính tốc độ, thì khi muốn tăng tốc cho giá trị này, chúng ta sẽ gọi phương thức để tăng tốc, thay vì gán giá trị trực tiếp cho thuộc tính này, phương thức sẽ nhận vào giá trị cần tăng tốc và kiểm tra xem giá trị này có phù hợp (lớn hơn 0, không được vượt quá 50 kmh chẳng hạn) hay không rồi mới gán cho thuộc tính, chứ các đối tượng bên ngoài không trực tiếp thao tác với thuộc tính đó.
Việc gom nhóm code thành các đối tượng có một số lợi ích như sau:
- Tính module hóa: việc phân nhóm các thuộc tính và các phương thức tương tự nhau vào một đối tượng đã vận dụng phương pháp chia-để-trị một cách triệt để, giúp quản lý thông tin dễ dàng hơn.
- Che giấu thông tin: thông tin của các đối tượng chỉ có thể được đọc/ghi thông qua phương thức chứ không được thao tác một cách trực tiếp, như thế dữ liệu sẽ không bị sửa chữa một cách bừa bãi, vô tổ chức.
- Tái sử dụng code: một đối tượng được tạo ra thì có thể sử dụng trong các chương trình khác, giúp việc kiểm tra, phát triển một cách dễ dàng.
- Dễ kiểm tra: nếu chẳng may chương trình bị lỗi, và một đối tượng nào đó có thể là nguyên nhân gây lỗi thì chúng ta chỉ cần xóa đối tượng đó ra và thay bằng một đối tượng mới.
Lớp – Class
Trong thế giới thực thì bạn sẽ thấy nhiều đối tượng giống nhau, chẳng hạn như có hàng ngàn chiếc xe đạp cùng tồn tại, cùng mẫu mã, cùng được sản xuất theo một quy trình và bản thiết kế như nhau, cùng có các bộ phận giống nhau.
Trong lập trình hướng đối tượng thì chúng ta gọi mỗi chiếc xe đạp là một thực thể của một lớp có tên là “Lớp xe đạp”.
Tóm lại một “lớp” có thể hiểu là một bản thiết kế của các đối tượng cụ thể nào đó.
Dưới đây là một đoạn code khai báo lớp Bicycle (xe đạp) tượng trưng trong Java:
class Bicycle { int speed = 0; int gear = 1; void changeGear(int newGear) { gear = newGear; } void speedUp(int value) { speed = speed + value; } }
Chúng ta sẽ tìm hiểu chi tiết về đoạn code sau. Nếu bạn đã từng lập trình trước đây rồi thì bạn có thể đoán trong đoạn code trên gear
và speed
là các thuộc tính/trường, changeGear()
và speedUp()
là các phương thức/hàm.
Trong đoạn code trên thì chúng ta không có phương thức main(),
bởi vì đây chỉ là bản thiết kế lớp xe đạp để được sử dụng ở nơi khác.
Chẳng hạn như chúng ta có lớp Demo
như sau:
class Demo { public static void main(String[] args) { Bicycle bike1 = new Bicycle(); Bicycle bike2 = new Bicycle(); bike1.speedUp(10); bike2.changeGear(2); } }
Chúng ta sẽ tìm hiểu kỹ hơn về code sau. Nếu bạn đã từng lập trình rồi thì có thể biết trong đoạn code trên chúng ta tạo ra 2 đối tượng Bicycle
là bike1
và bike2,
sau đó gọi phương thức speedUp()
cho bike1
và changeGear()
cho bike2.
Chúng ta không thay đổi giá trị cho các thuộc tính một cách trực tiếp, chẳng hạn như không dùng các câu lệnh như bike1.speed
= 10
hay đại loại như thế.