Kế Thừa, Đa Hình, Gói và Sửa Chữ Trong Java

Kế Thừa, Đa Hình, Gói và Sửa Chữ Trong Java

Phần 1: Kiểm Soát Truy Cập và Ghi Đè Phương Thức trong Kế Thừa

(1) Kiểm Soát Truy Cập

  1. Lớp con truy cập thành viên của lớp cha:
    • Lớp con chỉ có thể truy cập các thành viên không phải là private của lớp cha (public, protected, và quyền truy cập mặc định).
    • Nếu thành viên của lớp cha sử dụng private, lớp con không thể truy cập trực tiếp.
    • Ví dụ:
    class Cha {
        private int bienRieng = 10; // Lớp con không thể truy cập trực tiếp
        protected int bienProtected = 20; // Lớp con có thể truy cập
    }
    
    class Con extends Cha {
        public void hienThi() {
            // System.out.println(bienRieng); // Lỗi, không thể truy cập
            System.out.println(bienProtected); // Đúng
        }
    }
  2. Kế thừa phương thức khởi tạo:
    • Lớp con không thể kế thừa phương thức khởi tạo của lớp cha.
    • Tất cả các phương thức khởi tạo của lớp con mặc định sẽ gọi đến phương thức khởi tạo không tham số của lớp cha (super()) để khởi tạo các biến thành viên của lớp cha.
    • Nếu lớp cha không có phương thức khởi tạo không tham số, lớp con phải gọi rõ ràng phương thức khởi tạo có tham số của lớp cha.
    • Ví dụ:
    class Cha {
        public Cha(int a) {
            System.out.println("Phương thức khởi tạo của lớp Cha");
        }
    }
    
    class Con extends Cha {
        public Con() {
            super(10); // Gọi rõ ràng phương thức khởi tạo có tham số của lớp cha
            System.out.println("Phương thức khởi tạo của lớp Con");
        }
    }
  3. Truy cập biến thành viên:
    • super: truy cập biến thành viên của lớp cha.
    • this: truy cập biến thành viên của lớp hiện tại.
    • Nếu chỉ viết tên biến, nguyên tắc gần nhất sẽ được áp dụng (tìm kiếm trong phạm vi cục bộ trước, sau đó trong lớp hiện tại, và cuối cùng trong lớp cha).
    • Ví dụ:
    class Cha {
        int bien = 10;
    }
    
    class Con extends Cha {
        int bien = 20;
    
        public void hienThi() {
            System.out.println(super.bien); // Truy cập biến thành viên của lớp cha
            System.out.println(this.bien); // Truy cập biến thành viên của lớp hiện tại
            System.out.println(bien); // Truy cập biến thành viên của lớp hiện tại
        }
    }

(2) Ghi đè phương thức

  1. Định nghĩa:
    • Khi phương thức của lớp cha không đáp ứng được nhu cầu của lớp con, lớp con có thể ghi đè phương thức đó.
    • Bản chất là ghi đè phương thức trong bảng phương thức ảo của lớp cha, không ảnh hưởng đến phương thức của lớp cha.
    • Chỉ các phương thức được thêm vào bảng phương thức ảo (không phải private, static, final) mới có thể được ghi đè.
  2. Định dạng viết:
    • Phương thức của lớp con và lớp cha phải hoàn toàn giống nhau (tên phương thức, danh sách tham số).
    • Nên sử dụng chú thích @Override.
    • Ví dụ:
    class Cha {
        public void hienThi() {
            System.out.println("Phương thức hienThi của lớp Cha");
        }
    }
    
    class Con extends Cha {
        @Override
        public void hienThi() {
            System.out.println("Phương thức hienThi của lớp Con");
        }
    }
  3. Bảng phương thức ảo:
    • Khi kế thừa, các phương thức không phải private, static, final của lớp cha sẽ được trích xuất và đưa vào bảng phương thức ảo.
    • Nếu mối quan hệ kế thừa dài, bảng phương thức ảo có thể tăng hiệu quả tìm kiếm, tránh việc tìm kiếm từng cấp.

Phần 2: Đa Hình

(1) Định nghĩa đa hình

Đa hình là các đối tượng cùng kiểu nhưng biểu hiện dưới các hình thái khác nhau. Cú pháp:

LoạiLớpCha tênĐối tượng = Đối tượngLớpCon;

(2) Điều kiện của đa hình

  1. Có quan hệ kế thừa hoặc triển khai.
  2. Có tham chiếu lớp cha trỏ đến đối tượng lớp con.
  3. Có phương thức được ghi đè.

(3) Đặc điểm gọi thành viên trong đa hình

  1. Biến thành viên:
    • Thời gian biên dịch nhìn sang trái, thời gian chạy cũng nhìn sang trái.
    • Ví dụ:
    class DongVat {
        int tuoi = 10;
    }
    
    class Cho extends DongVat {
        int tuoi = 20;
    }
    
    DongVat d = new Cho();
    System.out.println(d.tuoi); // Xuất 10, thời gian biên dịch và chạy đều nhìn sang trái
  2. Phương thức thành viên:
    • Thời gian biên dịch nhìn sang trái, thời gian chạy nhìn sang phải.
    • Ví dụ:
    class DongVat {
        public void hienThi() {
            System.out.println("Phương thức hienThi của lớp DongVat");
        }
    }
    
    class Cho extends DongVat {
        @Override
        public void hienThi() {
            System.out.println("Phương thức hienThi của lớp Cho");
        }
    }
    
    DongVat d = new Cho();
    d.hienThi(); // Xuất "Phương thức hienThi của lớp Cho", thời gian chạy nhìn sang phải

(4) Lợi ích của đa hình

  1. Gi耦合:
    • Đối tượng bên phải có thể thực hiện việc giải coupling, giúp dễ dàng mở rộng và bảo trì.
    • Định nghĩa phương thức, sử dụng kiểu cha làm tham số, có thể nhận tất cả các đối tượng lớp con.
    • Ví dụ:
    public void choAn(DongVat dv) {
        dv.hienThi();
    }
  2. Tính linh hoạt:
    • Có thể sử dụng tham chiếu lớp cha để gọi phương thức của lớp con, thực hiện hành vi đa hình.

(5> Nhược điểm của đa hình

  1. Không thể gọi chức năng riêng của lớp con:
    • Thời gian biên dịch nhìn sang trái, không thể trực tiếp gọi phương thức riêng của lớp con.
    • Giải pháp: ép kiểu bắt buộc.
    • Ví dụ:
    DongVat d = new Cho();
    if (d instanceof Cho) {
        Cho c = (Cho) d;
        suaMeo(); // Gọi phương thức riêng của lớp con
    }
  2. Toán tử instanceof:
    • Dùng để xác định một đối tượng có phải là thể hiện của một lớp không, giá trị trả về là boolean.
    • Ví dụ:
    System.out.println(d instanceof Cho); // true

Phần 3: Gói và Nhập

(1) Khái niệm gói

  1. Định nghĩa:
    • Gói là thư mục trong Java, dùng để tổ chức lớp và giao diện.
    • Quy tắc sử dụng:
      • Các lớp trong cùng một gói không cần nhập.
      • Sử dụng các lớp trong gói java.lang không cần nhập.
      • Trong các trường hợp khác cần nhập.
      • Nếu hai gói có lớp cùng tên, cần sử dụng tên đầy đủ của lớp.
    • Ví dụ:
    package com.vd;
    
    import java.util.ArrayList; // Nhập lớp ArrayList
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            List<String> danhSach = new ArrayList<>();
        }
    }
  2. Chức năng của gói:
    • Tránh xung đột tên lớp.
    • Nâng cao khả năng bảo trì mã.

Phần 4: Sửa Chữ

(1) Sửa chữ final

  1. Biến:
    • Biểu thị biến không thể thay đổi (hằng số), chỉ có thể gán giá trị một lần.
    • Nếu là kiểu dữ liệu nguyên thủy, giá trị không đổi; nếu là kiểu dữ liệu tham chiếu, địa chỉ không thể thay đổi nhưng giá trị thuộc tính bên trong có thể thay đổi.
    • Ví dụ:
    final int MAX = 100; // Kiểu dữ liệu nguyên thủy
    final StringBuilder sb = new StringBuilder(); // Kiểu dữ liệu tham chiếu
  2. Phương thức:
    • Biểu thị phương thức cuối cùng, không thể bị ghi đè.
    • Ví dụ:
    public final void hienThi() {
        System.out.println("Phương thức final");
    }
  3. Lớp:
    • Biểu thị lớp cuối cùng, không thể được kế thừa.
    • Ví dụ:
    public final class LopCuoiCung {
    }

(2) Sửa chữ quyền truy cập

  1. Phạm vi:
    • private: chỉ có thể truy cập trong lớp này.
    • Mặc định (không có sửa chữ): truy cập trong cùng một gói.
    • protected: truy cập trong cùng một gói, hoặc lớp con truy cập.
    • public: có thể truy cập ở bất kỳ đâu.
    • Ví dụ:
    public class Cha {
        private int bienRieng; // Chỉ có thể truy cập trong lớp Cha
        int macDinh; // Truy cập trong cùng một gói
        protected int protectedVar; // Truy cập trong cùng một gói hoặc lớp con
        public int publicVar; // Có thể truy cập ở bất kỳ đâu
    }
  2. Quy tắc sử dụng:
    • Tất cả các biến thành viên nên được riêng tư (private).
    • Tất cả các phương thức nên được công khai (public).
    • Ví dụ:
    public class LopCuaToi {
        private int bien;
    
        public void setBien(int bien) {
            this.bien = bien;
        }
    
        public int getBien() {
            return bien;
        }
    }

(3) Khối tĩnh

  1. Định nghĩa:
    • Khối tĩnh (static {}) được viết giữa biến thành viên và phương thức khởi tạo.
    • Được tải cùng với lớp và chỉ thực thi một lần.

Thẻ: Java Kế thừa Đa hình Gói Sửa chữ

Đăng vào ngày 2 tháng 7 lúc 22:41