Bài 8. Kế thừa

Kế thừa (Inherit, Derive) „ Tái sử dụng mã nguồn (Reusability) Tạo lớp mới bằng cách phát triển lớp đã có. Lớp mới kế thừa những gì đã có trong lớp cũ và phát triển những tính năng mới. „ Lớp cũ: Lớp cha (parent, superclass) Lớp cơ sở(base class) „ Lớp mới: Lớp con (child, subclass) Lớp dẫn xuất (derived class)

pdf13 trang | Chia sẻ: lylyngoc | Lượt xem: 1682 | Lượt tải: 1download
Bạn đang xem nội dung tài liệu Bài 8. Kế thừa, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
11 LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG VỚI JAVA Nguyễn Thị Thu Trang trangntt-fit@mail.hut.edu.vn TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI KHOA CÔNG NGHỆ THÔNG TIN Bé m«n C«ng nghÖ phÇn mÒm Bài 8. Kế thừa (Inheritance) 2© Nguyễn Thị Thu Trang, SE-FIT-HUT Mục tiêu của bài học Sau khi kết thúc bài học, sinh viên có thể: „ Mô tả các khái niệm cơ bản liên quan đến kế thừa „ Giải thích nguyên lý kế thừa „ Chỉ ra thứ tự khởi tạo và hủy bỏ đối tượng trong kế thừa „ Trình bày nguyên lý định nghĩa lại trong kế thừa „ Sử dụng các vấn đề trên với ngôn ngữ lập trình Java. 3© Nguyễn Thị Thu Trang, SE-FIT-HUT Bài 8. Kế thừa (Inheritance) 1. Tổng quan về kế thừa 2. Nguyên lý kế thừa 3. Khởi tạo và hủy đối tượng 4. Định nghĩa lại 5. Lớp ảo và giao diện 4© Nguyễn Thị Thu Trang, SE-FIT-HUT Bài 8. Kế thừa (Inheritance) 1. Tổng quan về kế thừa 2. Nguyên lý kế thừa 3. Khởi tạo và hủy đối tượng 4. Định nghĩa lại 5. Lớp ảo và giao diện 25© Nguyễn Thị Thu Trang, SE-FIT-HUT 1. Tổng quan về kế thừa Ví dụ: „ Điểm Tứ giác gồm 4 điểm Æ Kết tập „ Tứ giác Hình vuông Æ Kế thừa 6© Nguyễn Thị Thu Trang, SE-FIT-HUT 1.1. Bản chất Kế thừa (Inherit, Derive) „ Tái sử dụng mã nguồn (Reusability) Tạo lớp mới bằng cách phát triển lớp đã có. Lớp mới kế thừa những gì đã có trong lớp cũ và phát triển những tính năng mới. „ Lớp cũ: Lớp cha (parent, superclass) Lớp cơ sở (base class) „ Lớp mới: Lớp con (child, subclass) Lớp dẫn xuất (derived class) Tứ giác Hình vuông Hình thang 7© Nguyễn Thị Thu Trang, SE-FIT-HUT 1.1. Bản chất (tiếp) Kế thừa (tiếp) „ Lớp con mở rộng (extend) từ lớp cha Là một loại của lớp cha Kế thừa được các thành phần dữ liệu và các hành vi của lớp cha Chi tiết hóa cho phù hợp với mục đích sử dụng mới „ Thêm các thuộc tính/hành vi mới „ Chỉnh sửa lại các hành vi kế thừa từ lớp cha. 8© Nguyễn Thị Thu Trang, SE-FIT-HUT 1.2. Phân biệt kế thừa và kết tập Kết tập tái sử dụng thông qua lại đối tượng. „ Tạo ra tham chiếu đến các đối tượng của các lớp có sẵn trong lớp mới Quan hệ “là một phần” (“is a part of”) Ví dụ: Ô tô có 4 bánh xe Kế thừa tái sử dụng thông qua lớp. „ Tạo lớp mới bằng cách phát triển lớp đã có sẵn Quan hệ “là một loại” (“is a kind of”) Ví dụ: Ô tô là một loại phương tiện vận tải Kế thừa Kết tập 39© Nguyễn Thị Thu Trang, SE-FIT-HUT 1.3. Cây phân cấp kế thừa Cây phân cấp kế thừa (Inheritance hierarchy) „ Cấu trúc phân cấp hình cây, biểu diễn mối quan hệ kế thừa giữa các lớp. „ Dẫn xuất trực tiếp B dẫn xuất trực tiếp từ A „ Dẫn xuất gián tiếp C dẫn xuất gián tiếp từ A A B C 10© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ về cây phân cấp kế thừa Hình Hình hai chiều Hình ba chiều Hình tròn Tứ giác Tam giác Hình cầu Hình lăng trụ Tứ diện 11© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ về cây phân cấp kế thừa Mọi đối tượng đều thừa kế từ lớp gốc Object 12© Nguyễn Thị Thu Trang, SE-FIT-HUT Bài 8. Kế thừa 1. Tổng quan về kế thừa 2. Nguyên lý kế thừa 3. Khởi tạo và hủy đối tượng 4. Định nghĩa lại 5. Lớp ảo và giao diện 413© Nguyễn Thị Thu Trang, SE-FIT-HUT 2. Nguyên lý kế thừa Thành viên protected trong lớp cha „ Là mức truy cập ở giữa public và private „ Được truy cập ở: Các thành viên lớp cha Các thành viên lớp con Các thành viên các lớp cùng thuộc 1 gói (package) Lớp con có thể kế thừa được gì? „ Kế thừa được các thành viên (bao gồm dữ liệu và phương thức) được khai báo là public và protected của lớp cha. „ Không kế thừa được các thành viên private. 14© Nguyễn Thị Thu Trang, SE-FIT-HUT 2. Nguyên lý kế thừa (2) Khác gói, non-inher Lớp con cùng gói Không có Lớp con khác gói Cùng lớp privateprotectedpublic 15© Nguyễn Thị Thu Trang, SE-FIT-HUT 2. Nguyên lý kế thừa (2) NoNoNoYesKhác gói, non-inher NoYesYesYesLớp con cùng gói No Yes Không có NoYesYesLớp con khác gói YesYesYesCùng lớp privateprotectedpublic 16© Nguyễn Thị Thu Trang, SE-FIT-HUT 2. Nguyên lý kế thừa (3) 517© Nguyễn Thị Thu Trang, SE-FIT-HUT 2.1. Cú pháp kế thừa trên Java Cú pháp kế thừa trên Java: „ extends Ví dụ: „ class HinhVuong extends TuGiac „ class Bird extends Animal 18© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 1 public class TuGiac { protected Diem d1, d2, d3, d4; public void setD1(Diem _d1) {d1=_d1;} public Diem getD1(){return d1;} public void draw(){//Vẽ tứ giác} … } public class HinhVuong extends TuGiac { public HinhVuong(){ d1 = new Diem(0,0); d2 = new Diem(0,1); d3 = new Diem(1,0); d4 = new Diem(1,1); } } public class Test{ public static void main(String args[]){ HinhVuong hv = new HinhVuong(); hv.draw(); } } Sử dụng các biến protected trong lớp con Gọi hàm public lớp cha của đối tượng lớp con 19© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 2 class Person { private String name; private Date bithday; public String getName() { return name; } ... } class Employee extends Person { private double salary; public boolean setSalary(double sal) { salary = sal; return true; } public String getDetail(){ String s = name+“,”+birthday+“,”+salary;//Loi } } 20© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 2 – sửa lại class Person { protected String name; protected Date bithday; public String getName() { return name; } ... } class Employee extends Person { private double salary; public boolean setSalary(double sal) { salary = sal; return true; } public String getDetail(){ String s = name+“,”+birthday+“,”+salary; } } 621© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 2 (tiếp) public class Test{ public static void main(String args[]){ Employee e = new Employee(); e.setName("John"); e.setSalary(3.0); } } 22© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 3 – Cùng gói public class Person { Date birthday; String name; ... } public class Employee extends Person { ... public String getDetail() { String s; String s = name + "," + birthday; s += ",“ + salary; return s; } } 23© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 3 – Khác gói package abc; public class Person { protected Date birthday; protected String name; ... } import abc.Person; public class Employee extends Person { ... public String getDetail() { String s; s = name + "," + birthday + "," + salary; return s; } } 24© Nguyễn Thị Thu Trang, SE-FIT-HUT 2.2. Các hàm không được phép kế thừa Các hàm không được phép kế thừa: „ Các hàm thiết lập và hàm hủy Làm nhiệm vụ khởi đầu và gỡ bỏ các đối tượng Chúng chỉ biết cách làm việc với từng lớp cụ thể „ Toán tử gán = Làm nhiệm vụ giống như hàm thiết lập 725© Nguyễn Thị Thu Trang, SE-FIT-HUT Bài 8. Kế thừa 1. Tổng quan về kế thừa 2. Nguyên lý kế thừa 3. Khởi tạo và hủy đối tượng 4. Định nghĩa lại 5. Lớp ảo và giao diện 26© Nguyễn Thị Thu Trang, SE-FIT-HUT 3. Khởi tạo và huỷ bỏ đối tượng Khởi tạo đối tượng: „ Lớp cha được khởi tạo trước lớp con. „ Các hàm khởi tạo của lớp con gọi hàm khởi tạo của lớp cha Không tường minh (implicit - tự động gọi) Tường minh (explicit - gọi trực tiếp). Hủy bỏ đối tượng: „ Ngược lại so với khởi tạo đối tượng 27© Nguyễn Thị Thu Trang, SE-FIT-HUT 3.1. Tự động gọi hàm khởi tạo lớp cha Hàm khởi tạo của lớp con tự động gọi hàm khởi tạo mặc định của lớp cha (dòng đầu tiên trong hàm khởi tạo). „ Hàm khởi tạo mặc định: Không tham số Do hệ thống tự cung cấp (nếu không được viết lại) hoặc do người dùng viết lại. „ Nếu lớp cha có hàm khởi tạo mặc định thì hàm khởi tạo này sẽ được tự động gọi trong câu lệnh đầu tiên của hàm khởi tạo lớp con. 28© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ public class TuGiac { protected Diem d1, d2; protected Diem d3, d4; public TuGiac(){ System.out.println("Lop cha TuGiac()"); } //… } public class HinhVuong extends TuGiac{ public HinhVuong(){ //Tu dong goi TuGiac() System.out.println("Lop con HinhVuong()"); } } public class Test { public static void main(String arg[]) { HinhVuong hv = new HinhVuong(); } } 829© Nguyễn Thị Thu Trang, SE-FIT-HUT 3.2. Gọi trực tiếp hàm khởi tạo của lớp cha Nếu lớp cha không có hàm khởi tạo mặc định tức là đã ghi chồng hàm khởi tạo của lớp cha với một số tham số thì „ Câu lệnh đầu tiên trong hàm khởi tạo của lớp con bắt buộc phải gọi hàm khởi tạo của lớp cha super(Danh sách tham số); „ Hàm khởi tạo của lớp con không bắt buộc phải có tham số. 30© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ public class TuGiac { protected Diem d1, d2; protected Diem d3, d4; public TuGiac(Diem _d1, Diem _d2, Diem _d3, Diem _d4){ System.out.println("Lop cha TuGiac(d1, d2, d3, d4)"); d1=_d1; d2=_d2; d3=_d3; d4=_d4; } //… } public class HinhVuong extends TuGiac { public HinhVuong(){ System.out.println("Lop con HinhVuong()"); } } public class Test { public static void main(String arg[]) { HinhVuong hv = new HinhVuong(); } } Lỗi 31© Nguyễn Thị Thu Trang, SE-FIT-HUT Gọi trực tiếp hàm khởi tạo của lớp cha Hàm khởi tạo lớp con không tham số public class TuGiac { protected Diem d1, d2; protected Diem d3, d4; public TuGiac(Diem _d1, Diem _d2, Diem _d3, Diem _d4){ System.out.println("Lop cha TuGiac(d1, d2, d3, d4)"); d1=_d1; d2=_d2; d3=_d3; d4=_d4; } //… } public class HinhVuong extends TuGiac{ public HinhVuong(){ super(new Diem(0,0),new Diem(0,1), new Diem(1,1),new Diem(1,0)); System.out.println("Lop con HinhVuong()"); } } HinhVuong hv = new HinhVuong(); 32© Nguyễn Thị Thu Trang, SE-FIT-HUT Gọi trực tiếp hàm khởi tạo của lớp cha Hàm khởi tạo lớp con có tham số public class TuGiac { protected Diem d1, d2; protected Diem d3, d4; public TuGiac(Diem _d1, Diem _d2, Diem _d3, Diem _d4){ System.out.println("Lop cha TuGiac(d1, d2, d3, d4)"); d1=_d1; d2=_d2; d3=_d3; d4=_d4; } //… } public class HinhVuong extends TuGiac{ public HinhVuong(Diem _d1, Diem _d2, Diem _d3, Diem _d4){ super(_d1, _d2, _d3, _d4); System.out.println("Lop con HinhVuong(d1, d2, d3, d4)"); } } HinhVuong hv = new HinhVuong(new Diem(0,0), new Diem(0,1), new Diem(1,1), new Diem(1,0)); 933© Nguyễn Thị Thu Trang, SE-FIT-HUT Bài 8. Kế thừa 1. Tổng quan về kế thừa 2. Nguyên lý kế thừa 3. Khởi tạo và hủy đối tượng 4. Định nghĩa lại 5. Lớp ảo và giao diện 34© Nguyễn Thị Thu Trang, SE-FIT-HUT 4. Định nghĩa lại hay ghi đè Lớp con có thể định nghĩa hàm trùng tên với hàm trong lớp cha: „ Nếu hàm mới chỉ trùng tên và khác chữ ký (số lượng hay kiểu dữ liệu của đối số) Æ Chồng hàm (Overloading) „ Nếu hàm mới hoàn toàn giống về giao diện (chữ ký) với hàm trong lớp cơ sở: Æ Định nghĩa lại hoặc ghi đè (redefining or override) 35© Nguyễn Thị Thu Trang, SE-FIT-HUT 4. Định nghĩa lại hay ghi đè (2) Phương thức override sẽ thay thế hoặc làm rõ hơn cho phương thức cùng tên trong lớp cha Đối tượng của lớp dẫn xuất sẽ hoạt động với phương thức mới phù hợp với nó Có tái sử dụng phương thức cùng tên của lớp cơ sở bằng từ khóa super 36© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ package abc; public class Person { protected Date birthday; protected String name; p g ; public String getDetail() {...} ... } import abc; public class Employee extends Person { ... public String getDetail() { String s = super.getDetail() + "," + salary; return s; } } 10 37© Nguyễn Thị Thu Trang, SE-FIT-HUT 4. Định nghĩa lại hay ghi đè (3) Một số quy định „ Danh sách tham số phải giống hệt phương thức trong lớp cha. „ Phải có cùng kiểu trả về với phương thức kế thừa 38© Nguyễn Thị Thu Trang, SE-FIT-HUT 4. Định nghĩa lại hay ghi đè (3) Một số quy định (tiếp) „ Các chỉ định truy cập không giới hạn chặt hơn phương thức trong lớp cha Ví dụ, nếu ghi đè một phương thức protected, thì phương thức mới có thể là protected hoặc public, mà không được là private. „ Không được phép ghi đè: Các hàm không được phép thay đổi (final hoặc const) Lớp cha là final class 39© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ class Parent { public void doSomething() {} private int doSomething2() { return 0; } } class Child extends Parent { protected void doSomething() {} private void doSomething2() {} } 40© Nguyễn Thị Thu Trang, SE-FIT-HUT Bài 8. Kế thừa 1. Tổng quan về kế thừa 2. Nguyên lý kế thừa 3. Khởi tạo và hủy đối tượng 4. Định nghĩa lại 5. Lớp ảo và giao diện 11 41© Nguyễn Thị Thu Trang, SE-FIT-HUT 5.1. Lớp trừu tượng (Abstract Class) Không thể thể hiện hóa (instantiate – tạo đối tượng của lớp) Chưa đầy đủ, thường được sử dụng làm lớp cha. Lớp con kế thừa nó sẽ hoàn thiện nốt. Để trở thành một lớp trừu tượng, cần: „ Khai báo với từ khóa abstract „ Chứa ít nhất một phương thức trừu tượng (abstract method - chỉ có chữ ký mà không có cài đặt cụ thể) public abstract void draw(); „ Lớp con khi kế thừa cần cài đặt cụ thể cho các phương thức trừu tượng. 42© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ: abstract class Learner { public abstract String getName(); public abstract int getAge(); public int getMaxGrade() { return getAge() - 5; } } Nếu một lớp có một hay nhiều phương thức trừu tượng thì nó là lớp trừu tượng và phải được khai báo abstract Lớp trừu tượng được dùng để gắn kết các lớp đã cài đặt đầy đủ. 5.1. Lớp trừu tượng (tiếp) 43© Nguyễn Thị Thu Trang, SE-FIT-HUT 5.2. Giao diện (Interface) Đa kế thừa (Multiple Inheritance) „ Một lớp có thể kế thừa nhiều lớp khác (lớp con có thể có nhiều lớp cha) „ C++ hỗ trợ đa kế thừa Đơn kế thừa (Single Inheritance) „ Một lớp chỉ được kế thừa từ một lớp khác (lớp con chỉ có một lớp cha). „ Java chỉ hỗ trợ đơn kế thừa Æ Đưa thêm khái niệm Giao diện (Interface) A B C D B A DC E F 44© Nguyễn Thị Thu Trang, SE-FIT-HUT 5.2. Giao diện (tiếp) Cho phép một lớp có thể kế thừa (thực thi - implement) nhiều giao diện một lúc. Không thể thể hiện hóa (instantiate) trực tiếp Để trở thành giao diện, cần „ Sử dụng từ khóa interface để định nghĩa „ Chỉ được bao gồm: Chữ ký các phương thức (method signature) Các khai báo hằng (static & final). „ Lớp thực thi giao diện Hoặc là lớp trừu tượng (abstract class) Hoặc là bắt buộc phải thực thi toàn bộ các phương thức trong giao diện. 12 45© Nguyễn Thị Thu Trang, SE-FIT-HUT 5.2. Giao diện (tiếp) Cú pháp thực thi trên Java: „ extends implements <Danh sách giao diện> „ extends Ví dụ: „ public interface DoiXung {…} public class HinhVuong extends TuGiac implements DoiXung {…} „ public interface FlyableThing {…} public class Bird extends Animal implements FlyableThing {…} 46© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 1 public interface DoiXung { abstract … } public abstract class TuGiac { protected Diem p1, p2, p3, p4; … } public class HinhVuong extends TuGiac implements DoiXung { … } 47© Nguyễn Thị Thu Trang, SE-FIT-HUT Ví dụ 2 abstract class TuGiac { protected Diem d1, d2; protected Diem d3, d4; // Phương thức final public final void draw(){ //Vẽ tứ giác } // Phương thức trừu tượng public abstract double getArea(); } class HinhVuong extends TuGiac { //Truy cập được các thành phần //dữ liệu d1, d2, d3, d4 public double area (){ // Tính diện tích hình vuông } public final void draw(){ // Vẽ hình vuông Æ Báo lỗi } } 48© Nguyễn Thị Thu Trang, SE-FIT-HUT Kết luận Kế thừa là một phương pháp để tái sử dụng mã nguồn Kế thừa dùng khi ta có quan hệ “là một loại - is a kind of”. Lớp con kế thừa toàn bộ tính năng của lớp cha và có thể phát triển thêm các tính năng mới. Trong Java, không hỗ trợ đa kế thừa Æ Đưa ra khái niệm Giao diện (Interface) cho phép lớp con có thể thực thi nhiều giao diện một lúc. Hàm khởi tạo lớp con có thể gọi hàm khởi tạo lớp cha tường minh hoặc không tường minh. Lớp con có thể định nghĩa lại hay ghi đè các phương thức đã định nghĩa trong lớp cha. 13 49© Nguyễn Thị Thu Trang, SE-FIT-HUT Câu hỏi Kế thừa là gì? So sánh kế thừa với kết tập? Nêu bản chất của nguyên lý kế thừa? Những hàm nào không được phép kế thừa và tại sao? So sánh lớp trừu tượng và giao diện? Nêu nguyên lý và thứ tự thực hiện của hàm khởi tạo trong kế thừa?
Tài liệu liên quan