Các khái niệm cơ bản của OOP
Trong lĩnh vực lập trình, Java là một trong những ngôn ngữ được sử dụng rộng rãi nhất hiện nay. Với tính linh hoạt và khả năng ứng dụng đa dạng, Java đã trở thành một công cụ quan trọng trong việc phát triển các ứng dụng web, mobile hay desktop.
Để có thể hiểu và sử dụng tối đa các tính năng của ngôn ngữ này, việc nắm vững các khái niệm cơ bản của OOP (Object Oriented Programming) là điều hết sức cần thiết. Trong bài viết này, chúng ta sẽ cùng tìm hiểu về các khái niệm cơ bản của OOP trong Java và cách áp dụng chúng vào việc lập trình.
Tính đóng gói (Encapsulation)
Tính đóng gói là một trong những khái niệm cơ bản nhất của OOP trong Java, cho phép chúng ta giấu đi các chi tiết bên trong một đối tượng và chỉ cho phép truy cập thông qua các phương thức đã được xác định trước. Việc này giúp bảo vệ dữ liệu của chương trình và đảm bảo tính toàn vẹn của các đối tượng.
Khái Niệm
Để hiểu rõ hơn về tính đóng gói, chúng ta hãy xem xét ví dụ sau:
public class Student {
private String name;
private int age;
public void setName(String newName) {
this.name = newName;
}
public String getName() {
return this.name;
}
public void setAge(int newAge) {
this.age = newAge;
}
public int getAge() {
return this.age;
}
}
Trong đoạn code trên, chúng ta có một lớp Student với hai thuộc tính là name và age. Tuy nhiên, để truy cập và thay đổi giá trị của các thuộc tính này, chúng ta phải sử dụng các phương thức setName, getName, setAge và getAge. Các thuộc tính này được khai báo là private, có nghĩa là chỉ có thể truy cập từ bên trong lớp. Điều này đảm bảo rằng dữ liệu của đối tượng sẽ không bị ảnh hưởng bởi các phần khác trong chương trình.
Ưu Điểm
Tính đóng gói mang lại nhiều lợi ích cho việc lập trình trong Java. Dưới đây là một số ưu điểm của tính đóng gói:
-
Bảo mật dữ liệu: như đã đề cập ở trên, tính đóng gói giúp bảo vệ dữ liệu của chương trình tránh khỏi sự can thiệp không mong muốn.
-
Dễ dàng sửa đổi: sử dụng các phương thức để truy cập và thay đổi thuộc tính giúp chúng ta có thể thay đổi cách lấy hoặc gán giá trị cho thuộc tính mà không làm ảnh hưởng đến các phần khác trong chương trình.
-
Tính tái sử dụng cao: khi sử dụng tính đóng gói, ta có thể tạo ra các đối tượng có các thuộc tính và phương thức tương tự nhau nhưng khác nhau về giá trị.
Kế Thừa (Inheritance)
Kế thừa là một khái niệm quan trọng trong OOP có thể giúp chúng ta tăng tính tái sử dụng và quản lý mã nguồn hiệu quả hơn. Bằng cách kế thừa, một lớp con có thể sử dụng lại các thuộc tính và các phương thức từ một lớp cha đã tồn tại.
Khái Niệm
Để minh họa cho khái niệm này, chúng ta sẽ sử dụng ví dụ về hai lớp con Student và Teacher kế thừa từ lớp cha Person.
public class Person {
private String name;
private int age;
public void setName(String newName) {
this.name = newName;
}
public String getName() {
return this.name;
}
public void setAge(int newAge) {
this.age = newAge;
}
public int getAge() {
return this.age;
}
}
public class Student extends Person {
private String id;
public void setId(String newId) {
this.id = newId;
}
public String getId() {
return this.id;
}
}
public class Teacher extends Person {
private String subject;
public void setSubject(String newSubject) {
this.subject = newSubject;
}
public String getSubject() {
return this.subject;
}
}
Như bạn có thể thấy, cả lớp Student và Teacher đều có sử dụng lại các thuộc tính name và age từ lớp cha Person. Điều này giúp tiết kiệm thời gian và công sức trong việc viết mã lặp lại và quản lý mã nguồn.
Ưu Điểm
Kế thừa là một tính năng hết sức hữu ích trong lập trình Java vì nó mang lại nhiều lợi ích như sau:
-
Tính tái sử dụng cao: việc kế thừa cho phép chúng ta sử dụng lại các thuộc tính và phương thức đã có trong lớp cha, giúp tiết kiệm thời gian và công sức trong việc viết mã.
-
Quản lý mã nguồn hiệu quả: khi có nhiều lớp con kế thừa từ cùng một lớp cha, việc thay đổi trong lớp cha sẽ tự động được áp dụng cho tất cả các lớp con, giúp quản lý mã nguồn hiệu quả hơn.
-
Giúp cho code trở nên dễ hiểu hơn: khi sử dụng kế thừa, ta có thể phân loại các lớp theo nhóm và dễ dàng hiểu được mỗi lớp có nhiệm vụ gì.
Đa Hình (Polymorphism)
Đa hình là một khái niệm quan trọng và một trong những tính chất cơ bản của OOP. Nó cho phép các đối tượng được khai báo một cách tổng quát và có thể thực hiện các hành động khác nhau tùy thuộc vào đối tượng được gán.
Khái Niệm
Để hiểu rõ hơn về đa hình, chúng ta sẽ xem xét ví dụ sau:
public interface Shape {
public void draw();
}
public class Circle implements Shape {
public void draw() {
System.out.println("Vẽ hình tròn");
}
}
public class Rectangle implements Shape {
public void draw() {
System.out.println("Vẽ hình chữ nhật");
}
}
Trong đoạn code trên, chúng ta đã khai báo một interface Shape và hai lớp Circle và Rectangle thực thi từ interface này. Tuy nhiên, cả hai lớp đều có phương thức draw() nhưng lại có nội dung khác nhau. Điều này cho phép chúng ta gọi cùng một phương thức draw() từ các đối tượng khác nhau và kết quả trả về sẽ phụ thuộc vào đối tượng được gán.
Shape circle = new Circle();
circle.draw(); // In ra "Vẽ hình tròn"
Shape rectangle = new Rectangle();
rectangle.draw(); // In ra "Vẽ hình chữ nhật"
Ưu Điểm
-
Linh hoạt hơn trong việc sử dụng các đối tượng: việc sử dụng đa hình cho phép chúng ta gọi các phương thức từ các đối tượng khác nhau dù chúng có cùng tên phương thức.
-
Thay đổi và bảo trì mã dễ dàng hơn: khi có thay đổi trong cấu trúc của các lớp, chúng ta chỉ cần sửa đổi code ở một nơi duy nhất là interface thay vì phải sửa đổi ở nhiều lớp khác nhau.
-
Giúp code trở nên dễ hiểu hơn: sử dụng đa hình giúp cá nhân hoá các tính năng, đồng thời giúp chúng ta dễ hiểu được mỗi phương thức của đối tượng có chức năng gì.
Lớp và đối tượng (Class and Object)
Lớp và đối tượng là hai khái niệm quan trọng và cũng là hai khái niệm cơ bản nhất trong OOP. Đây là hai khái niệm mà ta sẽ gặp liên tục khi lập trình bằng Java.
Khái Niệm
Để hiểu rõ hơn về lớp và đối tượng, chúng ta sẽ sử dụng lại ví dụ về lớp Student đã được đề cập ở phần tính đóng gói.
public class Student {
private String name;
private int age;
public void setName(String newName) {
this.name = newName;
}
public String getName() {
return this.name;
}
public void setAge(int newAge) {
this.age = newAge;
}
public int getAge() {
return this.age;
}
}
Trong đoạn code trên, chúng ta đã khai báo một lớp Student với hai thuộc tính là name và age cùng với các phương thức để truy cập và thay đổi giá trị của các thuộc tính này. Khi sử dụng lớp Student, ta có thể tạo ra nhiều đối tượng khác nhau và mỗi đối tượng sẽ có các giá trị khác nhau cho thuộc tính name và age.
Student student1 = new Student();
student1.setName("John");
student1.setAge(20);
Student student2 = new Student();
student2.setName("Mary");
student2.setAge(18);
Ưu Điểm
-
Dễ dàng quản lý mã nguồn: việc phân loại các thuộc tính và phương thức vào từng lớp riêng biệt giúp cho việc quản lý mã nguồn hiệu quả hơn.
-
Tính tái sử dụng cao: nhờ vào tính chất tái sử dụng của OOP, ta có thể tạo ra nhiều đối tượng từ cùng một lớp và tiết kiệm thời gian viết mã.
-
Giúp cho code trở nên dễ hiểu hơn: sử dụng lớp và đối tượng giúp cá nhân hoá các tính năng trong chương trình, đồng thời giúp chúng ta dễ hiểu được mỗi phương thức của đối tượng có chức năng gì.
Kết Luận: nắm vững và áp dụng các khái niệm này vào việc lập trình sẽ giúp cho chương trình của bạn trở nên dễ quản lý, dễ hiểu và dễ bảo trì hơn. Hy vọng rằng thông qua bài viết này, bạn đã có cái nhìn tổng quan về OOP trong Java và có thể áp dụng vào các dự án của mình một cách hiệu quả.