180 likes | 348 Views
Buổi 7 - Chương 4 Kế Thừa – Inheritance. Môn : Lập trình hướng đối tượng Trình bày : TRẦN ĐỨC TÂM. Bài toán cần giải quyết. Xây dựng chương trình quản lý việc tính lương cho nhân viên . Nhân viên có các thuộc tính là : mã số nhân viên , họ và tên , ngày sinh , số ngày làm việc .
E N D
Buổi 7 - Chương4KếThừa – Inheritance Môn: Lậptrìnhhướngđốitượng Trìnhbày: TRẦN ĐỨC TÂM
Bài toán cần giải quyết • Xâydựngchươngtrìnhquảnlýviệctínhlươngchonhânviên. • Nhânviêncócácthuộctínhlà: mãsốnhânviên, họvàtên, ngàysinh, sốngàylàmviệc. • Lươngcủanhânviênđượctínhbằngcôngthức: sốngàylàmviệcnhânvới 10 USD • Nhânviênbánhàngcòncóthêmthuộctínhsốsảnphẩmđãbántrongtháng. • Lươngnhânviênbánhàngđượctínhtheocôngthức: sốngàylàmviệcnhânvới 5 USD + sốsảnphẩmnhânvới 2 USD
Giải quyết bài toán – cách 1 • Copy & Paste classEmployee { privatestring iD; privatestring fullName; privateDateTime birthDate; privateint daysOfWork; publicint CalcSalary() { return daysOfWork * 10; } } classSaler { privatestring iD; privatestring fullName; privateDateTime birthDate; privateint daysOfWork; privateint productsOfSale; publicint CalcSalary() { return daysOfWork * 5 + productsOfSale * 2; } } Mãnguồnphảiviếtlạinhiềulần. Khótrongviệcbảotrì, nângcấpsaunày
Giải quyết bài toán – cách 2 • Double Duty classEmployee { privatestring iD; privatestring fullName; privateDateTime birthDate; privateint daysOfWork; privateint productsOfSale; privatebool isSaler; publicint CalcSalary() { if(isSaler) return daysOfWork * 5 + productsOfSale * 2; return daysOfWork * 10; } } Đoạn code sẽkhóquảnlý do 1 lớpđốitượngquảnlý 2 nhiệmvụ
Khái niệm về kế thừa • Biểudiễnmốiquanhệ “cha – con” (hay “1 dạngcủa”) giữacáclớpđốitượng • Lớpmang ý nghĩakháiquátđượcgọilàlớp cha, lớpcơsở (base class) • Lớpmang ý nghĩa chi tiết, cụthểgọilàlớp con, lớpdẫnxuất (derived class) • Kếthừatạokhảnăngxâydựnglớpmớitừlớpđãcó • Kếthừagiúptậndụngmãnguồnđãcó • Kếthừagiúpdễdàngsửachữa, nângcấp, mởrộnghệthống
Phân loại kế thừa • Có 2 loạikếthừa: đơnthừakếvàđathừakế • Đơnthừakế: mộtlớpchỉkếthừatừ 1 lớpcơsở • Đathừakế: mộtlớpđượckếthừatừnhiềulớpcơsở • Trong C#, khônghỗtrợđathừakế (cóthểdùngkháiniệm interface đểkhắcphụcvấnđềnày) Lớp cơ sở 1 Lớp cơ sở 2 Lớp cơ sở Lớp dẫn xuất Lớp dẫn xuất Đa thừa kế Đơn thừa kế
Một số nguyên tắc trong kế thừa • Cácthànhphầncủalớpdẫnxuất (lớp con) sẽbaogồm: • Cácthànhphầnđượckhaibáo ở lớpdẫnxuất • Cácthànhphầnđượckhaibáo ở lớpcơsở (lớp cha) • Lớpdẫnxuấtkhôngđượcquyềnxóađinhữngthànhphầnđãđượckhaibáo ở lớpcơsở
Cú pháp khai báo & mô hình biểu diễn • Cúphápkhaibáo lớpdẫnxuấtlớpcơsở ↓ ↓ classOtherClass : SomeClass { //declare members }
Cú pháp khai báo & mô hình biểu diễn • Môhìnhbiểudiễn Tênlớpcơsở Tên lớp dẫn xuất <tên field>: <kiểudữliệu> <tên property> {get;set;}: <tênkiểu> <tên field>: <kiểu dữ liệu> <tên property> {get;set;}: <tên kiểu> <tên method> (danhsáchthamsố): <tênkiểutrảvề> <tên operator> (danhsáchthamsố): <tênkiểutrảvề> <tên method> (danhsáchthamsố): <tênkiểutrảvề> <tên operator> (danhsáchthamsố): <tênkiểutrảvề>
classEmployee { public String ID; public String Name; public DateTime BirthDate; public int DaysOfWork; } classSaler: Employee { public int ProductsOfSale; } classProgram { staticvoid Main(string[] args) { Saler a = newSaler(); a.Name = "Nguyen Van A"; a.ID = "12345600"; } } Ví dụ minh họa • Trongvídụnày, đểđơngiản, chúng ta chocácthànhphầndữliệulàpublic Saler Employee ID: String Name: String BirthDate: DateTime DaysOfWork: int ProductsOfSale: int Sale(): void Lớp Saler kế thừa mọi thành phần của lớp Employee
Truy xuất thành phần của lớp cơ sở ở lớp dẫn xuất • Tùy vào tầm vực truy xuất (access modifier) của các thành phần lớp cơ sở mà ở lớp dẫn xuất có thể hoặc không được phép truy xuất
Che dấu thành phần của lớp cơ sở ở lớp dẫn xuất • Trường hợp ở lớp con có thành phần giống ở lớp cha, ta có thể dùng từ khóa “new” đặt trước khai báo thành phần để che dấu thành phần ở lớp cơ sở.
Che dấu thành phần của lớp cơ sở ở lớp dẫn xuất • Trườnghợp ở lớp con cóthànhphầngiống ở lớp cha, ta cóthểdùngtừkhóa “new” đặttrướckhaibáothànhphầnđểchedấuthànhphần ở lớpcơsở. classSomeClass// Base class { publicstring Field1 = "SomeClass Field1"; publicvoid Method1(string value) { Console.WriteLine("SomeClass.Method1: {0}", value);} } classOtherClass : SomeClass// Derived class { newpublicstring Field1 = "OtherClass Field1"; new publicvoid Method1(string value) { Console.WriteLine("OtherClass.Method1: {0}", value);} } classProgram { staticvoid Main() { OtherClass oc = newOtherClass(); oc.Method1(oc.Field1); } }
Từ khóa base • Từ khóa “base” cho phép truy xuất thành phần của lớp cơ sở • Lưu ý, không thể dùng từ khóa “base” để truy xuất thành phần private của lớp cơ sở classSomeClass // Base class { publicstring Field1 = "Field1 -- In the base class"; } classOtherClass : SomeClass // Derived class { newpublicstring Field1 = "Field1 -- In the derived class"; publicvoid PrintField1() { Console.WriteLine(Field1); // Access the derived class. Console.WriteLine(base.Field1); // Access the base class. } } classProgram { staticvoid Main() { OtherClass oc = newOtherClass(); oc.PrintField1(); } }
Quá trình thực thi hàm khởi tạo classA { public A() {Console.WriteLine("Base construction");} } classB : A { publicint Field; public B(int x) { Field = x; Console.WriteLine("Derived construction"); } } classProgram { staticvoid Main() { Bb = newB(1); } } • Quá trình thực thi hàm khởi tạo ở lớp dẫn xuất sẽ thực hiện theo quy trình: • Gọi hàm khởi tạo ở lớp cơ sở • Thực thi phần thân hàm khởi tạo ở lớp dẫn xuất • Mặc định, hàm khởi tạo mặc định của lớp cơ sở sẽ được gọi • Do đó, nếu ở lớp cơ sở không có hàm khởi tạo mặc định, sẽ bị báo lỗi
Tùy chọn gọi hàm khởi tạo của lớp cơ sở • Có thể quyết định gọi hàm khởi tạo nào của lớp cơ sở ở quá trình khởi tạo của lớp dẫn xuất classEmployee { public String ID; public String Name; public DateTime BirthDate; public int DaysOfWork; public Employee(String id, String name, String birthdate) { ID = id; Name = name; BirthDate = Convert.ToDateTime(birthdate); } } classSaler: Employee { public int ProductsOfSale; publicSaler(String id, String name, String birthdate, int pSale) : base(id, name, birthdate) { ProductsOfSale= pSale; } }
Kế thừa và con trỏ • Con trỏ (biến) thuộc kiểu lớp cơ sở thì chỉ có thể truy cập đến các thành phần thuộc lớp cơ sở • Con trỏ (biến) thuộc kiểu lớp cơ sở thì có thể trỏ đến (được gán bằng) đối tượng thuộc lớp con • Con trỏ (biến) thuộc kiểu lớp con thì không thể trỏ đến đối tượng thuộc lớp cơ sở