Quan hệ thừa kế trong JAVA (Phần 2)

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

1. Các quan hệ IS-A và HAS-A


Như đã trình bày trong các chương trước, khi một lớp kế thừa từ một lớp khác, ta nói rằng lớp con chuyên biệt hóa (mở rộng) lớp cha.


Nhưng liệu khi nào thì nên chuyên biệt hóa một lớp khác?


Nhớ lại rằng lớp cha là loại tổng quát, còn lớp con là loại cụ thể và chuyên biệt, là loại con của lớp cha. Nhìn từ khía cạnh khác, tập hợp các đối tượng mà lớp con đại diện là một tập con của các đối tượng mà lớp cha đại diện.


Do đó, để đưa ra lựa chọn đúng đắn cho vấn đề nên hay không nên để lớp X là lớp chuyên biệt hóa lớp Y, ta có một phương pháp hiệu quả:



"Kiểm tra quan hệ IS-A, nghĩa là xem thứ này có là thứ kia hay không"


Để xem X có nên là lớp con của Y hay không, ta đặt câu hỏi theo dạng:


  • Nếu phát biểu một cách tổng quát rằng loại X là một dạng / thứ / kiểu của loại Y thì có lý hay không?


Nếu câu trả lời là "Có", thì X có thể là lớp con của Y.


Ví dụ:



  • Tam giác là một hình (Triangle IS-A Shape)? Đúng
  • Mèo là một động vật họ Mèo (Cat IS-A Feline)? Đúng
  • Xe tải là một phương tiện giao thông (Truck IS-A Vehicle)? Đúng


Nghĩa là, Triangle có thể là lớp con của Shape, Cat có thể là lớp con của Feline, Truck có thể là lớp con của Vehicle.


Ta xét tiếp:



  • Phòng bếp là một cái nhà (Kitchen IS-A House)? Chắc chắn sai.
  • Ngược lại thì sao? Nhà là một phòng bếp (House IS-A Kitchen)? Đúng là có một số người vì phong tục hay điều kiện sống mà ngôi nhà của họ chỉ có một phòng duy nhất nên đó vừa là nơi nấu bếp vừa là phòng cho nhiều chức năng khác.


Tuy nhiên, các trường hợp đó chỉ là "một số", nên câu trả lời tổng quát vẫn là "Sai". Cho nên, Kitchen không thể là lớp con của House hay ngược lại.


Phòng bếp và nhà rõ ràng có liên quan đến nhau, nhưng không phải qua quan hệ thừa kế mà là một quan hệ chứa HAS-A.


Câu hỏi ở đây là:



  • Nhà có chứa một phòng bếp hay không (House HAS-A Kitchen)? Nếu câu trả lời là "Có", điều đó có nghĩa House có một biến thực thể kiểu Kitchen.


Nói cách khác, House có một tham 109 chiếu tới một đối tượng Kitchen, chứ House không chuyên biệt hóa Kitchen hay ngược lại.


Quan hệ HAS-A trong Java được cài đặt bằng tham chiếu đặt tại đối tượng chứa chiếu tới đối tượng thành phần.


Quan hệ HAS-A giữa hai lớp thể hiện một trong ba quan hệ:



  • Kết hợp (association)
  • Tụ hợp (aggregation)
  • Và hợp thành (composition) mà các tài liệu về thiết kế hướng đối tượng thường nói đến.


Giữa hai lớp có quan hệ kết hợp nếu như các đối tượng thuộc lớp này cần biết đến đối tượng thuộc lớp kia để có thể thực hiện được công việc của mình.


Chẳng hạn, một người nhân viên chịu sự quản lý của một người quản lý, ta có quan hệ kết hợp nối từ Employee tới Manager, thể hiện ở việc mỗi đối tượng Employee có một tham chiếu boss kiểu Manager.


Hợp thành và tụ hợp là các quan hệ giữa một đối tượng và thành phần của nó (cũng là đối tượng).


Khác nhau ở chỗ, với quan hệ hợp thành, đối tượng thành phần là phần không thể thiếu được của đối tượng chứa nó, còn với quan hệ tụ hợp thì ngược lại.


Ví dụ:



  • Một cuốn sách bao gồm nhiều trang sách và một cuốn sách không thể tồn tại nếu không có trang nào. Do đó giữa Book (sách) và Page (trang) có quan hệ hợp thành.
  • Thư viện có nhiều sách, nhưng thư viện không có cuốn sách nào vẫn là một thư viện, nên quan hệ giữa Library (thư viện) và Book là quan hệ tụ hợp.


Java không có cấu trúc nào dành riêng để cài đặt các quan hệ tụ hợp hay hợp thành.


Ta chỉ cài đặt đơn giản bằng cách đặt vào đối tượng chủ các tham chiếu tới đối tượng thành phần, hay nói cách khác là phân rã thành các quan hệ HAS-A.


Chẳng hạn quan hệ hợp thành giữa Book và Page có thể được phân rã thành 'Book HAS-A ArrayList' và nhiều quan hệ 'ArrayList HAS-A Page'.


Các ràng buộc khác được đảm bảo bởi các phương thức có nhiệm vụ khởi tạo hay sửa các tham chiếu đó.


Quay lại quan hệ IS-A, có một điểm cần lưu ý:



"Quan hệ thừa kế IS-A chỉ có một chiều"


Ví dụ:


  • "Tam giác là một hình" là phát biểu có lý, nhưng khẳng định theo chiều ngược lại, "Hình là một tam giác", thì không đúng.
  • Có nhiều hình là hình tam giác, nhưng cũng có vô số hình không phải hình tam giác.


Thực ra, lưu ý trên là hiển nhiên, nếu ta nhớ đến mô tả về lớp con tại mục trước: Lớp con chuyên biệt hóa lớp cha.

2. Khi nào nên dùng quan hệ thừa kế


Mục này liệt kê một số quy tắc hướng dẫn việc sử dụng quan hệ thừa kế trong thiết kế.


Tại thời điểm này, ta tạm bằng lòng với việc biết quy tắc. Việc hiểu quy tắc nếu chưa trọn vẹn thì sẽ được bồi đắp dần trong những phần sau.


NÊN dùng quan hệ thừa kế khi một lớp là một loại cụ thể hơn của một lớp cha.


Ví dụ:



  • Tài khoản tiết kiệm (saving account) là một loại tài khoản ngân hàng (bank account)
  • Do đó, SavingAccount là lớp con của BankAccount là hợp lí.


NÊN cân nhắc việc thừa kế khi ta có một hành vi (mã đã được viết) nên được dùng chung giữa nhiều lớp thuộc cùng một kiểu tổng quát nào đó.


Ví dụ, HinhVuong, HinhTronHinhTamGiac đều có thể cần được vẽ và hiển thị thông tin, nên việc đặt các chức năng đó tại một lớp cha Hinh là hợp lí.


Tuy vậy, cần lưu ý rằng mặc dù thừa kế là một trong những đặc điểm quan trọng của lập trình hướng đối tượng nhưng nó không nhất thiết là cách tốt nhất cho việc tái sử dụng hành vi.


Quan hệ thừa kế giúp ta khởi động việc tái sử dụng, và nó thường là lựa chọn đúng khi thiết kế, nhưng các mẫu thiết kế sẽ giúp ta nhận ra những lựa chọn khác tinh tế và linh hoạt hơn.


KHÔNG NÊN dùng thừa kế chỉ nhằm mục đích tái sử dụng code của một lớp khác, trong khi quan hệ giữa lớp cha và lớp con vi phạm một trong hai quy tắc ở trên.


Ví dụ:



  • Giả sử ta đã viết cho lớp ChuongCua (chuông cửa) một đoạn code dành riêng cho việc hiển thị thông tin, và giờ ta cần viết mã cho chức năng hienThiThongTin cho lớp Piano.
  • Không nên vì nhu cầu đó mà cho Piano làm lớp con của ChuongCua. Bởi vì Đàn piano không phải là một loại chuông cửa.


(Giải pháp nên chọn cho tình huống này là:


  • Phần code cho chức năng hienThiThongTin nên được đặt trong một lớp HienThi
  • Và sau đó, các lớp cần có chức năng hienThiThongTin sẽ kế thừa lớp HienThi (qua quan hệ HAS-A.)


KHÔNG NÊN dùng quan hệ thừa kế nếu lớp con và lớp cha không qua được thử nghiệm IS-A. Hãy tự kiểm tra xem lớp con có phải là một kiểu chuyên biệt của lớp cha hay không.


Ví dụ:



  • Bike IS-A Vehicle (xe đạp là một phương tiện giao thông) hợp lí.
  • Nhưng Vehicle IS-A Bike (phương tiện giao thông là một loại xe đạp) thì không được.

3. Lợi ích của quan hệ thừa kế


Quan hệ thừa kế trong thiết kế mang lại cho ta rất nhiều điều


Lợi ích thứ nhất: Tránh lặp các đoạn code bị trùng lặp



Ta có thể loại bỏ được những đoạn code trùng lặp bằng cách tách ra các hành vi chung của một nhóm các lớp đối tượng và đưa phần code đó vào một lớp cha.


Nhờ đó, khi ta cần sửa nó, ta chỉ cần cập nhật 
code ở duy nhất một nơi, và sửa đổi đó có hiệu lực tại tất cả các lớp kế thừa hành vi đó.


=> Công việc gói gọn trong việc sửa và dịch lớp cha.


Tóm lại:



Ta không phải động đến các lớp con!


Với ngôn ngữ Java, chương trình là một tập hợp các lớp.


Do đó, ta không cần phải dịch lại các lớp con để có thể dùng được phiên bản mới của lớp cha. Đòi hỏi duy nhất là phiên bản mới của lớp cha không phá vỡ cái gì của lớp con.


Nghĩa cụ thể của từ "phá vỡ" trong ngữ cảnh trên sẽ được trình bày chi tiết sau.


Tạm thời, ta chỉ cần hiểu rằng hành động đó có nghĩa là sửa cái gì đó tại lớp cha mà lớp con bị phụ thuộc vào, chẳng hạn như sửa kiểu tham số, hay kiểu trả về, hoặc tên của một phương thức nào đó.



Lợi ích thứ hai: Lớp con kế thừa toàn bộ lớp cha



Ta định nghĩa được một giao thức chung cho tập các lớp gắn kết với nhau bởi quan hệ thừa kế. Quan hệ thừa kế cho phép ta đảm bảo rằng tất cả các lớp con của một lớp đều có tất cả các phương thức mà lớp đó có.


Lưu ý rằng, khi nói về động vật bất kì, ý ta đang nói về đối tượng DongVat hay đối tượng thuộc bất cứ lớp nào có DongVat là tổ tiên trong cây phả hệ.


Khi ta định nghĩa một kiểu tổng quát (lớp cha) cho một nhóm các lớp, bất cứ lớp con nào trong nhóm đó đều có thể dùng thay cho vị trí của lớp cha.


Ta đã có Soi là một loại con của DongVat; một đối tượng Soi có tất cả các thuộc tính, hành vi mà một đối tượng DongVat có.


Vậy thì logic hiển nhiên:



  • Một đối tượng Soi có thể được coi là thuộc loại DongVat
  • Nơi nào dùng được DongVat thì cũng dùng được Soi.

Tổng kết


Như vậy, qua bài này bạn đã hiểu thêm về quan hệ thừa kế IS-AHAS-A trong Java. Ngoài ra, bạn cũng biết lợi ích của quan hệ thừa kế, biết khi nào nên sử dụng quan hệ thừa kế và triển khai chúng.


Bởi vì tất cả mọi thứ trong Java là lớp và đối tượng. Do đó quan hệ thừa kế giữa các lớp rất quan trọng trong quá trình HỌC JAVA. Hãy đọc lại, làm lại các ví dụ nhiều lần để ngấm được kiến thức về quan hệ thừa kế trong Java 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
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!