Nội dung• Giới thiệu về thừa kế • Lớp dẫn xuất với hàm tạo • Bổ từ protected • Định nghĩa lại hàm thành viên • Các thành viên không được thừa kế... Thừa kế - các thuật ngữ• Lớp cơ sở Còn
Trang 1Thừa kế (Inheritance)
GV: Phạm Văn Tùng
Bộ môn: KHMT & CNPM
Trang 2Nội dung
• Giới thiệu về thừa kế
• Lớp dẫn xuất với hàm tạo
• Bổ từ protected
• Định nghĩa lại hàm thành viên
• Các thành viên không được thừa kế
Trang 3Sử dụng lại mã nguồn
• Tồn tại nhiều lớp với tập các thuộc tính và phương thức tương tự nhau hoặc liên quan đến nhau
– Person, Student, Manager
• Xuất hiện nhu cầu sử dụng lại các mã nguồn đã viết
– Thông qua copy
– Thông qua cơ chế thừa kế
Trang 4Sử dụng lại mã nguồn (tiếp)
• Thông qua copy
– Tốn công copy, dễ nhầm lẫn
– Khó sửa lỗi do tồn tại nhiều phiên bản
• Thông qua thừa kế
– Kĩ thuật lập trình rất mạnh và mềm dẻo
Trang 5Giới thiệu về thừa kế
• Thừa kế
– Chúng ta có thể tạo ra một lớp khác từ một lớp đã có sẵn mà không cần viết lại (copy lại) mã
– Lớp mới được thừa hưởng các thuộc tính (biến thành viên) và các phương thức (hàm thành viên) của lớp đã
Trang 6Thừa kế - các thuật ngữ
• Lớp cơ sở (Còn gọi là lớp cha)
– Là lớp dùng để tạo nên lớp khác
• Lớp dẫn xuất (Còn gọi là lớp con)
– Là một lớp mới được tạo ra từ lớp cơ sở
– Tự động có các thành viên của lớp cha
• Biến thành viên
• Hàm thành viên
– Có thể có thêm các biến thành viên hoặc hàm thành viên của riêng nó
Trang 7Thừa kế - ví dụ
• Xét ví dụ: Lớp Employee biểu diễn các nhân viên
Trang 8Thừa kế - ví dụ (tiếp)
Trang 9Thừa kế - ví dụ (tiếp)
• Cần xây dựng lớp HourlyEmployee để biểu diễn các nhân viên hưởng lương theo giờ
– Sử dụng cơ chế thừa kế
Trang 10Thừa kế - ví dụ (tiếp)
Trang 12Thừa kế - ví dụ (tiếp)
• Lớp HourlyEmployee có những biến thành viên:
– Các biến thành viên của lớp Employee: name,
ssn, netPay
– Các biến được định nghĩa thêm: wageRate, hours
• Tương tự như vậy lớp HourlyEmployee có các hàm thành viên bao gồm:
– Các hàm thành viên được thừa kế từ lớp Employee:
getName, setName, getSsn,…
– Các hàm thành viên được thêm mới: getRate,
setRate, getHours, setHours,…
Trang 13Thừa kế - định nghĩa lại hàm thành
viên
• Trong lớp dẫn xuất chúng ta có thể định nghĩa lại
hàm thành viên được thừa kế từ lớp cơ sở
– Làm cho hàm đấy phù hợp với lớp dẫn xuất
– Trong định nghĩa của lớp dẫn xuất phải liệt kê ra hàm muốn định nghĩa lại
Ví dụ: Hàm printCheck() được định nghĩa lại trong lớp dẫn xuất
Trang 14Định nghĩa lại so với nạp chồng
• Hai khái niệm này hoàn toàn khác nhau
• Định nghĩa lại hàm trong lớp dẫn xuất
– Danh sách tham số không thay đổi
– Chỉ là viết lại định nghĩa hàm đấy cho phù hợp
• Nạp chồng
– Danh sách tham số khác nhau
– Định nghĩa nên một hàm hoàn toàn mới
Trang 15Truy cập đến hàm thành viên được
định nghĩa lại của lớp cơ sở
• Khi hàm thành viên của lớp cơ sở được định nghĩa lại trong lớp dẫn xuất thì thực chất nó không bị mất đi
• Có thể sử dụng được hàm thành viên đấy của lớp cơ
sở thông qua đối tượng của lớp dẫn xuất
Trang 16Truy cập đến hàm thành viên được
định nghĩa lại của lớp cơ sở
• Employee JaneE;
HourlyEmployee SallyH;
JaneE.printCheck(); Gọi hàm printCheck
của lớp Employee SallyH.printCheck(); Gọi hàm printCheck
của lớp HourlyEmployee SallyH.Employee::printCheck(); Gọi hàm
printCheck của lớp Employee!
Trang 17Hàm tạo của lớp dẫn xuất
• Lớp dẫn xuất KHÔNG kế thừa hàm tạo của lớp cơ sở
– Phải khởi tạo một cách tường minh cho các biến thành viên kế thừa từ lớp cơ sở
– Chúng ta có thể gọi hàm tạo của lớp cơ sở bên trong hàm tạo của lớp dẫn xuất
• Hàm tạo của lớp cơ sở nên khởi tạo cho tất cả các
biến thành viên lớp cơ sở
– Hàm tạo của lớp dẫn xuất chỉ đơn giản gọi hàm tạo
của lớp cơ sở
Trang 18Hàm tạo của lớp dẫn xuất
• Xem xét cú pháp hàm tạo của lớp HourlyEmployee
HourlyEmployee::HourlyEmployee(string
theName, string theNumber, double
theWageRate, double theHours)
: Employee(theName, theNumber),
wageRate(theWageRate), hours(theHours) {
//Thân hàm tạo rỗng }
• Nhớ lại rằng phần sau dấu : được gọi là mục khởi tạo
– Có chứa lời gọi đến hàm tạo lớp cơ sở
Trang 19Hàm tạo lớp dẫn xuất (tiếp)
• Xét một hàm tạo khác của lớp HourlyEmployee
HourlyEmployee::HourlyEmployee():
Employee(), wageRate(0), hours(0)
{
//Deliberately empty }
• Hàm tạo mặc định của lớp cơ sở được gọi
• Trong hàm tạo của lớp dẫn xuất luôn gọi một hàm tạo của lớp cơ sở.
Trang 20Hàm tạo của lớp dẫn xuất (tiếp)
• Trong hàm tạo lớp dẫn xuất luôn gọi một hàm tạo lớp
cơ sở
• Nếu chúng ta không gọi tường minh
– Hàm tạo mặc định của lớp cơ sở sẽ được tự động gọi– Định nghĩa của hàm tạo mặc định lớp
HourlyEmployee trong slide bên tương đương với:
HourlyEmployee::HourlyEmployee()
: wageRate(0), hours(0) { }
Trang 21Cạm bẫy: Biến thành viên
private của lớp cơ sở
• Lớp dẫn xuất thừa kế các biến thành viên private của lớp cơ sở
– Nhưng ta vẫn KHÔNG THỂ truy cập trực tiếp đến
các biến này trong lớp dẫn xuất
– Phải truy cập thông qua các hàm truy cập và biến đổi
• Biến thành viên private CHỈ có thể được truy cập
trực tiếp trong các hàm thành viên của lớp mà chứa biến private đó
Trang 22Hàm private
• Hàm thành viên của lớp cũng có thể là private
– Thường là các hàm mang tính trợ giúp cho các hàm
Trang 23– Các thành viên protected cho cho phép thừa kế về sau
Trang 24Bổ từ protected – ví dụ
Trang 25– Được xem là mối quan hệ “có một”
– Ví dụ: Một AirpPlane (máy bay) có một
JetEngine (động cơ)
Trang 26Thừa kế - một vài vấn đề khác
• Thừa kế protected và private
– Một dạng thừa kế khác nhưng ít được sử dụng
• Đa thừa kế
– Một lớp dẫn xuất từ nhiều lớp cơ sở
– Phức tạp và khá nguy hiểm => Ít được sử dụng