Lập trình hướng đối tượng trong Java

Đặc điểm cốt lõi của OOP

Đóng gói (Encapsulation)

Ẩn giấu chi tiết bên trong, chỉ tiết lộ giao diện cần thiết. Giúp bảo vệ dữ liệu và tăng khả năng tái sử dụng.

Kế thừa (Inheritance)

Cho phép lớp con thừa hưởng thuộc tính và phương thức từ lớp cha. Lớp con có thể ghi đè phương thức khi cần mở rộng hành vi.

Đa hình (Polymorphism)

Cùng một thao tác nhưng cho kết quả khác nhau tùy theo đối tượng thực thi. Thường đạt được qua kế thừa, ghi đè và ép kiểu lên.

Ví dụ minh họa

public class NhanVien {
    private String hoTen;
    private int namSinh;
    
    NhanVien() {}
    
    NhanVien(String hoTen, int namSinh) {
        this.hoTen = hoTen;
        this.namSinh = namSinh;
    }
    
    public String gioiThieu() {
        return String.format("Tôi là %s, sinh năm %d", hoTen, namSinh);
    }
}
public class KySu extends NhanVien {
    
    KySu(String hoTen, int namSinh) {
        super(hoTen, namSinh);
    }
    
    @Override
    public String gioiThieu() {
        return "Nghề nghiệp: Kỹ sư. " + super.gioiThieu();
    }
    
    public String lapTrinh() {
        return "Đang viết code...";
    }
}
public class BacSi extends NhanVien {
    
    BacSi(String hoTen, int namSinh) {
        super(hoTen, namSinh);
    }
    
    @Override
    public String gioiThieu() {
        return "Nghề nghiệp: Bác sĩ. " + super.gioiThieu();
    }
    
    public String khamBenh() {
        return "Đang khám bệnh cho bệnh nhân...";
    }
}

Thực thi đa hình

NhanVien nv1 = new KySu("Minh Anh", 1995);
NhanVien nv2 = new BacSi("Thanh Hà", 1988);

System.out.println(nv1.gioiThieu()); // Nghề nghiệp: Kỹ sư...
System.out.println(nv2.gioiThieu()); // Nghề nghiệp: Bác sĩ...

Ép kiểu trong phân cấp kế thừa

public class CoSo {
    public void thaoTacChung() {
        System.out.println("[CoSo] Phương thức chung - liên kết tĩnh");
    }
    
    public void thaoTacDeGhiDe() {
        System.out.println("[CoSo] Chưa ghi đè");
    }
}
public class DanXuat extends CoSo {
    public void thaoTacRieng() {
        System.out.println("[DanXuat] Phương thức độc quyền");
    }
    
    @Override
    public void thaoTacDeGhiDe() {
        System.out.println("[DanXuat] Đã ghi đè - liên kết động");
    }
}

Ép kiểu lên (Upcasting)

Tham chiếu lớp cha trỏ đến đối tượng lớp con. Phương thức ghi đè sẽ được gọi theo kiểu động.

CoSo doiTuong = new DanXuat();
doiTuong.thaoTacChung();       // [CoSo] Phương thức chung...
doiTuong.thaoTacDeGhiDe();     // [DanXuat] Đã ghi đè...

Ép kiểu xuống (Downcasting)

Chuyển tham chiếu lớp cha về lớp con để truy cập phương thức đặc thù. Cần đảm bảo đối tượng thực sự thuộc lớp con để tránh ClassCastException.

if (doiTuong instanceof DanXuat) {
    DanXuat chuyenDoi = (DanXuat) doiTuong;
    chuyenDoi.thaoTacRieng();    // [DanXuat] Phương thức độc quyền
}

Lớp trừu tượng và Giao diện

Đặc điểmLớp trừu tượng (abstract)Giao diện (interface)
Số lượng kế thừaĐơn kế thừaĐa kế thừa
Khởi tạoKhông thể trực tiếpKhông thể trực tiếp
Phương thứcCó thể có phương thức thườngJava 8+: có default và static
Mục đíchCơ sở triển khai chungĐịnh nghĩa hợp đồng/hành vi

Ví dụ về giao diện trong Java 8+

public interface MayTinh {
    // Hằng số ngầm định
    double PI = 3.14159;
    
    // Phương thức trừu tượng
    double tinhToan(double a, double b);
    
    // Phương thức mặc định (Java 8)
    default void hienThiThongSo() {
        System.out.println("Máy tính với PI = " + PI);
    }
    
    // Phương thức tĩnh (Java 8)
    static String phienBan() {
        return "MayTinh v2.0";
    }
}

Lưu ý quan trọng về quy tắc

  • Ghi đè (Override): Cùng tên, cùng tham số, cùng kiểu trả về (hoặc kiểu con). Dùng @Override để kiểm tra.
  • Nạp chồng (Overload): Cùng tên, khác tham số (số lượng/khác kiểu). Kiểu trả về không quyết định nạp chồng.
  • Thứ tự khởi tạo: Khối tĩnh → Biến tĩnh → Khối khởi tạo → Constructor.
  • Lớp con không kế thừa được thành phần private của lớp cha.

Thẻ: Java oop inheritance polymorphism interface

Đăng vào ngày 21 tháng 8 lúc 16:20