Bài giảng Tính kế thừa và đa hình

Làm việc với mảng đối tượng  Giải thích được:  Thừa kế là gì trong OOP.  Các loại thừa kế trong các ngôn ngữOOP.  Đa hình là gì trong OOP.  Phân biệt được kỹ thuật Overloading và overriding.  Hiện thực được đặc điểm thừa kế trong OOP với Java.  Hiện thực được đặc điểm đa hình trong OOP với Java.  Sử dụng được toán tử instanceOf và ép kiểu trong Java  Giải thích được những tình huống có thể xẩy ra khi ép kiểu.  Giải thích được loại tham số trong hàm của Java.

pdf16 trang | Chia sẻ: haohao89 | Lượt xem: 2732 | Lượt tải: 3download
Bạn đang xem nội dung tài liệu Bài giảng Tính kế thừa và đa hình, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
1TÍNH KẾ THỪA VÀ ĐA HÌNH INHERITANCE - POLYMORPHISM 2 Ôn tập  Accsess modifier: chỉ thị mức độ cho phép bên ngoài truy cập vào một dữ liệu hay một hành vi của 1 lớp.  Khi thiết kế 1 lớp: Các yếu tố sau cần được xem xét để chọn access modifier phù hợp.  Constructor: Hành vi được thực thi ngay lúc khởi tạo đối tượng.  Tập các constructor tạo ra tập các mẫu khởi tạo biến đối tượng.  Một đối tượng sống từ lúc đối tượng được khởi tạo (bằng new) cho đến khi khối chứa nó được thực thi xong.  Phạm vi của 1 đối tượng là vùng văn bản chương trình từ lúc định nghĩa biến đến hết khối chứa biến này.  Destructor: Hành vi được thực thi vào lúc đối tượng chết ( Java không hỗ trợ destructor). 3 Đặc tính truy xuất Modifier private friendly protected public Cùng class YES YES YES YES Cùng gói, khác class NO YES NO YES lớp con trong cùng gói với lớp cha NO YES YES YES Khác gói, khác lớp NO NO NO YES Lớp con khác gói với lớp cha NO NO YES YES 4 Mục tiêu  Làm việc với mảng đối tượng  Giải thích được:  Thừa kế là gì trong OOP.  Các loại thừa kế trong các ngôn ngữ OOP.  Đa hình là gì trong OOP.  Phân biệt được kỹ thuật Overloading và overriding.  Hiện thực được đặc điểm thừa kế trong OOP với Java.  Hiện thực được đặc điểm đa hình trong OOP với Java.  Sử dụng được toán tử instanceOf và ép kiểu trong Java  Giải thích được những tình huống có thể xẩy ra khi ép kiểu.  Giải thích được loại tham số trong hàm của Java. 5 Nội dung  Mảng đối tượng  Lớp ArrayList  Thành phần static  Chỉ thị final  Tính kế thừa – Inheritance.  Superclass và Supclass  Các loại thừa kế.  Hiện thực lớp con trong Java.  Từ khóa super  Tính đa hình.  Kỹ thuật Overriding  Quan hệ qiữa các lớp  Toán tử instanceof  Vấn đề ép kiểu trong Java  Tham số của hàm trong Java 6 Mảng các đối tượng  Các phần tử của một mảng có thể là những tham chiếu đối tượng String[] words = new String[10]; HinhChuNhat[] arr_hcn = new HinhChuNhat[5];  Ngay khi khởi tạo, một mảng đối tượng giữ các tham chiếu null  Mỗi một đối tượng lưu trữ trong một mảng phải được tạo riêng biệt nhau words object stores 10 references to String objects arr_hcn object stores 5 references to HinhChuNhat objects 7Mảng các đối tượng  Mảng words ngay khi được khai báo: words - - - - -  Ngay tại thời điểm này, tham chiếu dưới đây sẽ đưa ra một NullPointerException: System.out.println (words[0]); 8 Mảng các đối tượng  Sau khi một vài đối tượng String được tạo và được lưu trữ trong mảng: “friendship”words - - “loyalty” “honor” Words[0] = new String(“friendship”); Words[1] = new String(“loyalty”); Words[2] = new String(“honor”); 9 Mảng các đối tượng  Sau khi một vài đối tượng HinhChuNhat được tạo và được lưu trữ trong mảng: (5,4)arr_hcn - - (7,3) (100,50) arr_hcn[0] = new HinhChuNhat(5,4); arr_hcn[1] = new HinhChuNhat(7,3); arr_hcn[2] = new HinhChuNhat(100,50); 10 Ví dụ - Mảng các đối tượng  Một sơ đồ UML cho chương trình MainHCN: MainHCN + main (args : String[]) : void HinhChuNhatCollection - collection : HinhChuNhat[] - count : int + addHinhChuNhat (cd : double, cr : double) : void + toString() : String - increaseSize() : voidHinhChuNhat- cdai : double - crong : double + toString() : String * 1 •Xem HinhChuNhat •Xem Array_HinhChuNhat •Xem MainHCN 11 Bài tập - Mảng các đối tượng  Mô hình UML cho chương trình Tunes: Tunes + main (args : String[]) : void CDCollection - collection : CD[] - count : int - totalCost : double + addCD (title : String, artist : String, cost : double, tracks : int) : void + toString() : String - increaseSize() : voidCD - title : String - artist : String - cost : double - tracks : int + toString() : String * 1 12 Lớp ArrayList  Lớp ArrayList đặt trong gói java.util  Giống như mảng, đối tượng ArrayList có thể lưu trữ danh sách các giá trị và tham chiếu, mỗi phần tử sử dụng một số chỉ mục (index)  Tuy nhiên, chúng ta có thể sử dụng cú pháp dấu ngoặc đơn (bracket) với một đối tượng ArrayList.  Đối tượng ArrayList tăng và giảm kích thước khi cần thiết, điều chỉnh dung lượng của nó khi cần thiết.  Khai báo: ArrayList name = new ArrayList(); 13 Lớp ArrayList  Những phần tử được thêm vào hoặc xóa đi thông qua việc gọi một phương thức của lớp.  Khi một phần tử trong mảng được thêm vào thì những phần tử khác “di chuyển sang một bên" để tạo khoảng trống  Tương tự như vậy, khi một phần tử được xóa đi, danh sach “thu bớt" để đóng khoảng trống  Chỉ mục của các phần tử được điều chỉnh cho phù hợp  Một vài phương thức của lớp ArrayList: 14 Những phương thức của lớp ArrayList  ArrayList() Constructor: creates an initially empty list.  boolean add (Object obj)  Inserts the specified object to the end of this list.  void add (int index, Object obj)  Inserts the specified object into this list at the specified index.  void clear() Removes all elements from this list.  Object remove (int index) Removes the element at the specified index in this list and returns it.  Object get (int index) Returns the object at the specified index in this list without removing it.  int indexOf (Object obj) Returns the index of the first occurrence of the specified object.  boolean contains (Object obj) Returns true if this list contains the specified object.  boolean isEmpty() Returns true if this list contains no elements.  int size() Returns the number of elements in this list. 15 Beatles.java import java.util.ArrayList; public class Beatles { public static void main (String[] args) { ArrayList band = new ArrayList(); band.add ("Paul"); band.add ("Pete"); band.add ("John"); band.add ("George"); System.out.println (band); int location = band.indexOf ("Pete"); band.remove (location); System.out.println (band); System.out.println ("At index 1: " + band.get(1)); band.add (2, "Ringo"); System.out.println ("Size of the band: " + band.size()); } } 16 Lớp ArrayList  Một ArrayList được phép lưu trữ bất kỳ kiểu đối tượng nào.  Chúng ta cũng có thể định nghĩa một đối tượng ArrayList để chấp nhận một kiểu đối tượng cụ thể  Ví dụ: ArrayList alName = new ArrayList(); ArrayList alHT = new ArrayList(); 17 Vòng lặp ArrayList  Ví dụ for (HinhChuNhat h : arrHCN) { System.out.println(“Chu vi la:” + h.ChuVi()); System.out.println(“Dien tich la:” + h.DienTich()); } for (Object o : arraylistName) { // process o } 18 Ví dụ - Mảng các đối tượng ArrayList  Một sơ đồ UML cho chương trình MainHCN: MainHCN + main (args : String[]) : void HinhChuNhatCollection - collection : HinhChuNhat[] - count : int + addHinhChuNhat (cd : double, cr : double) : void + toString() : StringHinhChuNhat - cdai : double - crong : double + toString() : String * 1 • Xem ArrayList_HinhChuNhat • Xem MainHCN 19 Bài tập - Mảng các đối tượng ArrayList  Mô hình UML cho chương trình Tunes: Tunes + main (args : String[]) : void CDCollection - collection : ArrayList - count : int - totalCost : double + addCD (ID: String,title : String, artist : String): boolean cost : double, tracks : int) : void + toString() : String + DeleteCD(ID:String): boolean + FindCD(ID: String): CD CD - ID : String - title : String - artist : String - cost : double - tracks : int + toString() : String * 1 20 Thành phần static  Đôi khi ta muốn một dữ liệu, một đoạn code, một hành vi là toàn cục để trongmột lớp Dùng chỉ thị static.  Dữ liệu static là DỮ LIỆU TOÀN CỤC.  Hành vi static là hành vi toàn cục  Code static là CODE TOÀN CỤC và chỉ thao tác lên dữ liệu static.  Truy xuất dữ liệu và code này thông qua tên lớp hoặc một đối tượng thuộc lớp có thành phần static. (1) ClassName.StaticMember (2) ClassName obj= new ClassName(); obj. StaticMember 21 Dữ liệu static- Thí dụ Truy xuất static data bằng tên lớp Truy xuất static data bằng tên đối tượng thuộc lớp 22 Ví dụ - Hành vi static Nhận xét Hành vi static được bên ngoài sử dụng mà không cần khai báo biến đối tượng thuộc lớp. Do vậy, hành vi static thường có tham số không liên quan đến đối tượng thuộc lớp. 23 Ví dụ - Code static Cú pháp đưa một đoạn code static: static { } Code static được thực thi ngay khi lớp có code này được tham chiếu tới. 24 Ví dụ - Code static Code static chỉ tham chiếu dữ liệu static 25 Ví dụ - Code static Nếu có nhiều đoạn code static, các đoạn code này được thực thi tuần tự 26 Code static với constructor tham chiếu khi chưa có đối tượng tham chiếu khi đã có đối tượng Vì khi có đối tượng, constructor có code làm thay đổi trị của n nên kết qủa đã khác đi. 27 Chỉ thị final  Làm sao để không cho phép kế thừa từ một lớp ( lớp không con).  Làm sao không cho phép sửa một dữ liệu ( muốn dữ liệu là hằng).  Dùng chỉ thị final 28 final Data là hằng cấm sửa 29 final class là lớp không con 30 final method là hành vi không cho phép lớp con viết lại (override) Phương thức final 31 Tính kế thừa – Inheriatance  Lập trình hướng đối tượng cho phép bạn phát triển những lớp mới từ các lớp đã tồn tại.  Khả năng một lớp thừa hưởng data và code từ một hay nhiều lớp khác.  Kỹ thuật giúp tái sử dụng code Tiết kiệm công sức lập trình, công sức kiểm tra code.  Vd: lớp B được phát triển từ lớp A: A B B inherits A 32 Superclass và Subclass  Vd: lớp B được phát triển từ lớp A:  B: subclass, extended class, derived class  A: superclass, parent class, base class  Subclass thừa kế từ superclass các trường dữ liệu và phương thức có thể truy xuất được, và cũng có thể thêm vào các trường dữ liệu và phương thức mới. 33 Superclass và Subclass (tiếp)  Thực tế, subclass thường được mở rộng để chứa nhiều thông tin chi tiết và nhiều chức năng hơn so với superclass của nó. Circle Cylinder1 TestCylinder1 34 Tính kế thừa- Inheritance ID_Num Name YearOfBirth Address getID_Num() setID_Num(newID) ...... class PERSON RollNum Score getScore() setSore(newScore) ...... class STUDENT quan hệ “is a” Chỉ phải hiện thực bằng này Để được cái tương đương ID_Num Name YearOfBirth Address getID_Num() setID_Num(newID) ...... class STUDENT RollNum Score getScore() setSore(newScore) ...... thừa kế tính chất riêng Con = Cha + một tí 35 Kỹ thuật phân cấp thừa kế (1) Liệt kê đặc điểm của các đối tượng cần quan tâm. (2) Tìm tập giao của các tính chất giữa các lớp, tách tập giao này để xây dựng lớp cha. (3) Đặt 1 tên gọi có ý nghĩa cho lớp cha. (4) Phần còn lại sau khi tách tập giao là các lớp con. 36 Các loại thừa kế.  Đơn thừa kế  Đa thừa kế ( thừa kế bội)  Mỗi ngôn ngữ OOP hỗ trợ khả năng thừa kế riêng.  C++ : đa thừa kế.  C# , Java : Đơn thừa kế 37 Hiện thực thừa kế trong Java. class CLASSNAME extends FATHERCLASSNAME { DataType1 Property1 [=Value]; DataType2 Property1 [=Value]; CLASSNAME (DataType Arg,…) // constructor {… } [Modifier] DataType MethodName(DataType Arg,…) { … } } Lớp con là mở rộng của lớp cha Từ khóa dùng trong thừa kế 38 Ví dụ  Cylinder kế thừa Circle Circle Cylinder 39 Ví dụ Circle - radius: double + Circle () + Circle (r : double) + getRadius() : double + setRadius(r : double) : void + findArea() : double Cylinder - length: double + Cylinder() + Cylinder (r : double, l : double) + getLength() : double + setLength (l : double) : void + findVolume() : double TestCylinder + main (args : String[]) : void Sơ đồ lớp cho TestCylinder 40 Circle.java public class Circle { private double radius; public Circle() { radius = 1.0; } public Circle (double r) { radius = r; } public double getRadius() { return radius; } public void setRadius (double r) { radius = r; } public double findArea() { return radius*radius*Math.PI; } } Circle - radius: double + Circle () + Circle (r : double) + getRadius() : double + setRadius(r : double) : void + findArea() : double 41 Cylinder.java public class Cylinder extends Circle { private double length; public Cylinder() { radius = 1.0; length = 1.0; } public Cylinder (double r, double l) { radius = r; length = l; } public double getLength() { return length; } public void setLength (double l) { length = l; } public double findVolume() { return findArea()*length; } } Cylinder - length: double + Cylinder() + Cylinder (r : double, l : double) + getLength() : double + setLength (l : double) : void + findVolume() : double Error, setRadius(1.0) Error, setRadius(r) 42 TestCylinder.java public class TestCylinder { public static void main (String[] args) { Cylinder c = new Cylinder (5.0, 5.2); System.out.println(“The radius is “ + c.getRadius()); System.out.println(“The length is “ + c.getLength()); System.out.println(“The area of the circle is “ + c.findArea()); System.out.println(“The volume of the cylinder is “ + c.findVolume()); } } 43 Sử dụng từ khóa super  super được dùng để thay cho superclass, tương tự như this thay cho đối tượng được gọi.  Dùng super để: - gọi 1 constructor của superclass - gọi 1 phương thức của superclass - gọi 1 biến thuộc tính của superclass 44 Gọi Superclass Constructor  super(), hoặc super(tham_số)  Lệnh trên phải được đặt tại dòng đầu tiên trong constructor của subclass và là cách duy nhất để gọi 1 constructor của superclass. public Cylinder() { } public Cylinder() { super(); } 45 Gọi thành viên của Superclass  super.tên_phương_thức(tham_số)  super.tên_biến thuộc_tính Vd: - double findVolume() { return super.findArea() * length; } 46100 emp mng p 200 300 P01 Hoa 21 P02 Luan 25 150 P03 Quang 25 150 200 100 200 300 Ví dụ 47 Bổ từ truy xuất public protected none (no modifier) private Visibility increase public class C1 { public int x; protected int y ; int z; private int u; protected void m () { } } public class C2 { C1 o = new C1(); can access o.x; can access o.y; can access o.z; cannot access o .u; can invoke o.m(); } public class C3 extends C1 { can access x; can access y; can access z; cannot access u ; can invoke m(); } public class C4 extends C1 { can access x; can access y; cannot access z ; cannot access u ; can invoke m(); } public class C5 { C1 o = new C1(); can access o.x; cannot access o .y; cannot access o .z; cannot access o .u; cannot invoke o .m(); } package p 1; package p 2; 48 private và protected modifiers  Sử dụng private để ẩn hoàn toàn các thành phần của class (dữ liệu, phương thức), chúng sẽ không thể được truy xuất trực tiếp từ bên ngoài lớp.  Sử dụng protected để cho phép các thành phần của class được truy xuất bởi các subclass trong bất kỳ package nào, hoặc các class trong cùng package.  2 từ khóa trên chỉ có thể sử dụng cho các thành phần của class, không thể sử dụng cho class. 49 public và default modifiers  Sử dụng default modifier (no modifier) thì các thành phần của class được truy xuất từ bất kỳ lớp nào trong cùng package, nhưng không thể từ package khác.  Sử dụng public cho phép các thành phần của class có thể được truy xuất từ bất kỳ lớp nào.  public và default modifier có thể được sử dụng cho các thành phần của class, cũng như sử dụng cho chính class. 50 Chú ý  Các ký hiệu -, #, + được sử dụng để biểu diễn tương ứng các modifier private, protected, và public.  Khi chồng phương thức:  Nếu phương thức trong superclass là protected thì có thể thay đổi phương thức chồng trong subclass thành public.  Nhưng nếu phương thức trong superclass là public thì phương thức chồng trong subclass bắt buộc cũng phải là public. 51 Ví dụ 1 Circle # radius : double + Circle() + Circle(r : double) + getRadius() : double + setRadius(r : double) : void + Area() : double Cylinder - length : double + Cylinder() + Cylinder (r : double, l : double) + getLength() : double + setLength (l : double) : void + Volume() : double TestCylinder + main (args : String[]) : void Sơ đồ lớp cho TestCylinder 52 Circle.java public class Circle { protected double radius; public Circle() { radius = 1.0; } public Circle (double r) { radius = r; } public double getRadius() { return radius; } public void setRadius (double r) { radius = r; } public double Area() { return radius*radius*Math.PI; } }Circle # radius : double + Circle() + Circle(r : double) + getRadius() : double + setRadius(r : double) : void + Area() : double 53 Cylinder.java public class Cylinder extends Circle { private double length; public Cylinder() { //super(); radius=1.0; length = 1.0; } public Cylinder (double r,double l) { //super (r); radius=r; length = l; } public double getLength() { return length; } public void setLength (double l) { length = l; } public double Volume() { return super.Area() * length; } } Cylinder - length : double + Cylinder() + Cylinder(r : double, l : double) + getLength() : double + setLength(l : double) : void + Volume() : double 54 Ví dụ 2 Book2 # pages : int + Book (numPages : int) + setPages (numPages : int): void + getPage() : int Dictionary2 - definitions : int + Dictionary (numPages: int, numDefinitions: int) + computeRatio() : double + setDefinitions (numDefinitions : int) : void + getDefinitions() : int Words2 + main (args : String[]) : void 55 Book2.java public class Book2 { protected int pages; public Book2 (int numPages) { pages = numPages; } public void setPages (int numPages) { pages = numPages; } public int getPages () { return pages; } } Book2 # pages : int + Book (numPages : int) + setPages (numPages : int): void + getPage() : int 56 Dictionary2.java public class Dictionary2 extends Book2 { private int definitions; public Dictionary2 (int numPages, int numDefinitions) { super(numPages); definitions = numDefinitions; } public double computeRatio () { return definitions/super.pages; } public void setDefinitions (int numDefinitions) { definitions=numDefinitions; } public int getDefinitions () { return definitions; } } Dictionary2 - definitions : int + Dictionary (numPages: int, numDefinitions: int) + computeRatio() : double + setDefinitions (numDefinitions : int) : void + getDefinitions() : int 57 Words2.java public class Words2 { public static void main (String[] args) { Dictionary2 w = new Dictionary2 (1500, 52500); System.out.println ("Number of pages: " + w.getPages()); System.out.println ("Number of definitions: " + w.getDefinitions()); System.out.println ("Definitions per page: " + w.computeRatio()); } } 58 Bài tập Nguoi # SoCNMD: String # HoTen: String # NgaySinh: String ( hoặc Date) # Diachi: String + Nguoi (SoCMND, Hoten, Ngaysinh, Diachi) + setCMND (SoCMND : String): void + getCMND() : String + setHoten (Hoten : String): void + getHoten() : String + setNgaysinh (Ngaysinh : String): void + getNgaysinh() : String + setDiachi(Diachi : String): void + getDiachi() : String SinhVien - MSSV : String - DiemLT, DiemTH: double + setDiemLT(diemLT: double) + setDiemTH(diemLH: double) + DiemTB () : double + toString : String + SinhVien(MaSV, Hoten, SoCMND, Diachi, Ngaysinh, DiemLT, DiemTH) Test_Student + main (args : String[]) : void 59 Bài tập Phân tích phân cấp thừa kế cho các lớp:  Hàng điện máy <mã hàng, tên hàng, nhà sản xuất, giá, thời gian bảo hành, điện áp, công suất>  Hàng sành sứ < mã hàng, tên hàng, nhà sản xuất, giá, loại nguyên liệu>  Hàng thực phẩm <mã hàng, tên hàng, nhà sản xuất, giá, ngày sản xuất, ngày hết hạn dùng>  Viết chương trình tạo mỗi loại một mặt hàng cụ thể. xuất thông tin về các mặt hàng này.  Gợi ý: cách viết tương tự ví dụ trên. 60 Tính đa hình - Polymorphism  Đa hình thái, nhiều cách phản ứng khác nhau cho cùng một hành vi.  Lớp A có hành vi M().  Lớp B là con của lớp A, trong lớp B viết lại hành vi M().  Có biến đối tượng o