Quan hệ thừa kế trong JAVA

Ngày đăng: 15/12/2020   -    Cập nhật: 15/12/2020


Thừa kế là một trong những nguyên lý của lập trình hướng đối tượng giúp ta có thể xây dựng chương trình một cách nhanh chóng và hiệu quả hơn, thu được kết quả là những mô-đun chương trình mà các lập trình viên khác dễ mở rộng hơn, có khả năng đáp ứng tốt hơn đối với sự thay đổi liên tục của các yêu cầu của khách hàng. Vậy thừa kế là gì?

1. Khái quát về quan hệ thừa kế


Khi ta dùng quan hệ thừa kế trong thiết kế, ta đặt các phần code dùng chung tại một lớp và coi đó là lớp cha – lớp dùng chung trừu tượng hơn, các lớp cụ thể hơn là các lớp con.


Quan hệ thừa kế trong JAVA


Các lớp con được thừa kế từ lớp cha đó. Quan hệ thừa kế có nghĩa rằng lớp con được thừa hưởng các thành viên (member) của lớp cha. Thành viên của một lớp là các biến thực thể và phương thức của lớp đó.


Ví dụ như lớp SinhVien có các thành viên như ten, tuoi, setTen(), getTen(), setTuoi(), getTuoi(),…


Ta còn nói rằng lớp con chuyên biệt hóa (specialize) lớp cha. Nghĩa của "chuyên biệt hóa" ở đây gồm có hai phần:



  • Lớp con là một loại con của lớp cha – thể hiện ở chỗ lớp con tự động thừa hưởng các thành viên của lớp cha
  • Lớp con có những đặc điểm của riêng nó - thể hiện ở chỗ lớp con có thể bổ sung các phương thức và biến thực thể mới của riêng mình, và nó có thể cài đè (override) các phương thức thừa kế từ lớp cha.


Hãy quan sát hình sau:


Minh họa quan hệ thừa kế trong JAVA


Trong hình trên, chúng ta có HinhChuNhat cũng là một hình đa giác (HinhDaGiac), do đó lớp con HinhChuNhat có tất cả những gì mà HinhDaGiac có.


Ngoài ra, HinhChuNhat có thêm những đặc điểm riêng:



  • Nó cũng có thể xoay nhưng có thể xoay theo cách riêng
  • Nó cũng có thể thông báo nhưng thông báo theo cách riêng.
  • Ngoài ra nó có thể có thêm các điểm riêng khác như chỉ có 4 cạnh,... trong đó 2 cạnh đối diện thì bằng nhau....
  • ...


Theo thuật ngữ - và cũng là từ khóa của Java, lớp con "nối dài", "mở rộng" (extends) lớp cha.


Các biến thực thể không bị ghi đè vì việc đó là không cần thiết. Biến thực thể không quy định một hành vi đặc biệt nào và lớp con chỉ việc gán giá trị tùy chọn cho biến được thừa kế.

2. Các bước thiết kế cây thừa kế


Giả sử ta cần thiết kế một chương trình giả lập cho phép người dùng thả một đám các con động vật thuộc các loài khác nhau vào một môi trường để xem chuyện gì xảy ra. Ta hiện chưa phải viết code mà mới chỉ ở giai đoạn thiết kế.


Ta biết rằng mỗi con vật sẽ được đại diện bởi một đối tượng, và các đối tượng sẽ di chuyển loanh quanh trong môi trường, thực hiện các hành vi được lập trình cho loài vật đó. Ta được giao một danh sách các loài vật sẽ được đưa vào chương trình: sư tử, hà mã, hổ, chó, mèo, sói.


Và ta muốn rằng, khi cần, các lập trình viên khác cũng có thể bổ sung các loài vật mới vào chương trình.


Bước 1, ta xác định các đặc điểm chung và trừu tượng mà tất cả các loài động vật đều có – năm biến thực thể và 4 phương thức:



  • ten – tên của con vật này
  • thucAn – loại thức ăn mà con vật thích. Hiện giờ, biến này chỉ có hai giá trị: Cỏ hoặc Thịt.
  • doi – một biến int biểu diễn mức độ đói của con vật (ví dụ từ 1 đến 10, 10 là đói nhất). Biến này thay đổi tùy theo khi nào con vật ăn và nó ăn bao nhiêu
  • tiengKeu() – hành vi khi con vật phát ra tiếng kêu
  • an() – hành vi khi con vật gặp nguồn thức ăn ưa thích, thịt hoặc cỏ.
  • ngu() – hành vi khi con vật được coi là đang ngủ.
  • diKiemAn() – hành vi khi con vật không phải đang ăn hay đang ngủ, có thể chỉ đi lang thang đợi gặp món gì ăn được hoặc gặp biên giới lãnh địa.



public class DongVat {

    String ten = "Tên";
    String thucAn = "";
    int doi = 0;

    public void tiengKeu() {
        System.out.println("Tiếng kêu");
    }

    public void an() {
        System.out.println("Đang ăn...");
    }

    public void ngu() {
        System.out.println("Đang ngủ...");
    }

    public void diKiemAn() {
        System.out.println("Đi kiếm ăn...");
    }
}
 


Bước 2, thiết kế một lớp với tất cả các thuộc tính và hành vi chung kể trên.


Đây sẽ là lớp mà tất cả các lớp động vật đều có thể chuyên biệt hóa. Các đối tượng trong ứng dụng đều là các con vật, do đó, ta sẽ gọi tên lớp cha chung của chúng là DongVat.


Ta đưa vào đó các phương thức và biến thực thể mà tất cả các con vật đều có thể cần. Kết quả là ta được lớp cha là lớp tổng quát hơn, hay nói cách khác là trừu tượng hơn, còn các lớp con mang tính đặc thù hơn, chuyên biệt hơn lớp cha.


Ta đã biết rằng mỗi loại DongVat đều có tất cả các biến thực thể đã khai báo cho DongVat, do đó:



  • Một con sư tử sẽ có các giá trị riêng cho ten, thucAn, doi
  • Một con hà mã sẽ có những giá trị khác cho bộ biến thực thể tương tự
  • Cũng như vậy đối với chó, hổ...


Thế còn các hành vi của chúng thì sao?


Bước 3: Xác định xem các lớp con có cần các hành vi (cài đặt của các phương thức) đặc thù của thể loại con cụ thể đó hay không?


Để ý lớp DongVat. Chắc chắn sư tử không ăn giống hà mã. Còn về tiếng kêu, ta có thể viết duy nhất một phương thức tiengKeu() tại DongVat trong đó có thể in ra tiếng kêu khác nhau tùy loài, để con vật này kêu khác con vật khác.


Nhưng làm vậy có vẻ chưa đủ vì tùy từng tình huống mà các loài khác nhau phát ra các tiếng kêu khác nhau, chẳng hạn tiếng kêu khi đang ăn và tiếng kêu khi gặp kẻ thù, v.v..


Do đó, ta quyết định rằng an()tiengKeu() nên được ghi đè tại từng lớp con.


Tạm coi các con vật ngu()diKiemAn() như nhau và không cần ghi đè hai phương thức này.


Ngoài ra, một số loài có những hành vi riêng đặc trưng của loài đó, chẳng hạn chó có thêm hành vi đuổi mèo ( duoiMeo() ) bên cạnh các hành vi mà các loài động vật khác cũng có.


Ví dụ, trong thực tế, sói, chó và sư tử chúng cùng có xu hướng di chuyển theo đàn để kiếm ăn nên có thể dùng chung một phương thức diKiemAn().


Mèo và hổ, hai loài này có thể sử dụng chung phương thức diKiemAn() vì khi di chuyển chúng cùng có xu hướng đi một mình.


Ta sẽ để cho hà mã tiếp tục dùng phương thức diKiemAn() tổng quát được thừa kế từ DongVat.


3. Ghi đè phương thức


Lớp Cho có bốn phương thức: ngu() được thừa kế từ DongVat, roam() được thừa kế từ Soi (thực ra là phiên bản ghi đè của DongVat), và hai phương thức mà Soi ghi đè của DongVat - tiengKeu()diKiemAn().


Class Soi mở rộng (kế thừa) class DongVat




public class Soi extends DongVat {

    String ten = "Sói";
    String thucAn = "Thịt";

    // Ghi đè phương thức của lớp DongVat
    public void tiengKeu() {
        System.out.println("Hú hú hú....");
    }

    public void diKiemAn() {
        System.out.println("Đi kiếm ăn một mình...");
    }
}
 


Còn đây là class Cho kế thừa class Soi



public class Cho extends Soi {
    
    String ten = "Chó";

    // Ghi đè phương thức tiengKeu()
    public void tiengKeu() {
        System.out.println("Gâu gâu gâu...");
    }
}
 


Khi ta tạo một đối tượng Cho và gán một biến tham chiếu tới nó, ta có thể dùng biến đó để gọi cả bốn phương thức trên. Nhưng phiên bản nào của chúng đó sẽ được gọi?


Khi gọi phương thức từ một tham chiếu đối tượng, ta đang gọi phiên bản đặc thù nhất của phương thức đó đối với lớp của đối tượng cụ thể đó.


Nếu hình dung cây thừa kế theo kiểu các lớp cha ở phía trên còn các lớp con ở phía dưới, thì quy tắc ở đây là: Phiên bản thấp nhất sẽ được gọi.


Trong ví dụ dùng biến c để gọi phương thức cho một đối tượng Cho ở trên, thứ tự từ thấp lên cao lần lượt là Cho, Soi, DongVat.


Khi gọi một phương thức cho một đối tượng Cho, máy ảo Java bắt đầu tìm từ lớp Cho lên, nếu nó không tìm được một phiên bản của phương thức đó tại Cho thì nó chuyển lên tìm tại lớp tiếp theo bên trên Cho ở cây thừa kế, cứ như vậy cho đến khi tìm thấy một phiên bản khớp với lời gọi phương thức.


Với ví dụ đang xét, c.tiengKeu() sẽ dẫn đến việc kích hoạt phiên bản của Cho, c.diKiemAn() gọi phiên bản của Soi, v.v..


Ta tạo ra một class Test (file Test.java) để chuyên thử nghiệm việc tạo ra các động vật:




public class Test {

    public static void main(String[] args) {
        Cho c = new Cho();

        // Tên thật của Chó
        c.ten = "Mốc";

        // Kiểm tra tình trạng đói
        System.out.println("Tình trạng đói: " + c.doi);

        // Đói quá
        c.doi = 7;

        // Nếu đói quá thì đi kiếm ăn
        while (c.doi > 5) {
            System.out.println("Đói quá...");
            c.diKiemAn();
            c.doi--;
        }

        // Kêu thử xem
        c.tiengKeu();
    }
    
}
 


Kết quả khi chạy chương trình trên là:



Tình trạng đói: 0
Đói quá...
Đi kiếm ăn một mình...
Đói quá...
Đi kiếm ăn một mình...
Gâu gâu gâu...
 

Tổng kết


Như vậy, trong bài hướng dẫn này, bạn đã được tìm hiểu sơ bộ về quan hệ thừa kế trong Java. Tuy nhiên, trong Java còn có các kiểu thừa kế IS-A, HAS-A và nhiều vấn đề khác nữa chúng ta sẽ tìm hiểu trong bài viết sau.


> Nếu bạn yêu thích ngôn ngữ JAVA thì có thể đẩy nhanh quá trình học tập, làm sản phẩm thành công bằng cách tham gia HỌC JAVA tại NIIT - ICT Hà Nội bạn nhé.



---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học thực tế + Tuyển dụng ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
 
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python
Bình luận Facebook
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!