Bài giảng Lập trình hướng đối tượng - Chương 3: Lập trình Hướng đối tượng với Java (P2) - Trần Minh Thái

1. Vấn đề tái sử dụng code 2. Kế thừa trong Java 3. Tính đa hình trong Java 4. Cài đặt interface trong Java 5. Lập trình tổng quát Vấn đề tái sử dụng code Lập trình cấu trúc: chương trình con OOP: nhiều loại đối tượng có thuộc tính, hành vi tương tự nhau  tái sử dụng các lớp đã viết Trong một lớp vẫn tái sử dụng phương thức Ưu điểm: Giảm chi phí Nâng cao khả năng bảo trì và khả năng mô hình hóa

pptx118 trang | Chia sẻ: candy98 | Lượt xem: 544 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Bài giảng Lập trình hướng đối tượng - Chương 3: Lập trình Hướng đối tượng với Java (P2) - Trần Minh Thái, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Chương 3 Lập trình Hướng đối tượng với Java (tt)TRẦN MINH THÁIEmail: minhthai@huflit.edu.vnWebsite: www.minhthai.edu.vn Cập nhật: 02 tháng 07 năm 2016Nội dungVấn đề tái sử dụng codeKế thừa trong JavaTính đa hình trong JavaCài đặt interface trong JavaLập trình tổng quátVấn đề tái sử dụng codeLập trình cấu trúc: chương trình conOOP: nhiều loại đối tượng có thuộc tính, hành vi tương tự nhau  tái sử dụng các lớp đã viếtTrong một lớp vẫn tái sử dụng phương thứcƯu điểm: Giảm chi phíNâng cao khả năng bảo trì và khả năng mô hình hóaCác hình thức tái sử dụng codeSao chép lớp cũ thành 1 lớp khác  Hạn chế: Dư thừa, khó quản lý khi có thay đổiKết hợp: Lớp mới là tập hợp hoặc sử dụng các lớp đã cóKế thừa: Lớp mới phát triển thêm các thuộc tính hoặc phương thức từ lớp đã cóKết hợp (Aggregation)Thành phần lớp mới chứa các đối tượng của lớp cũLớp mới: Lớp chứa/Lớp toàn thểLớp cũ: Lớp thành phầnVí dụ:Lớp cũ: Điểm (Point)Lớp mới: Tam giác (Triangle) có 3 điểmLớp chứa tái sử dụng các thuộc tính và phương thức của lớp thành phần thông qua đối tượngKý hiệu Kết hợp1 số nguyên dương (1, 2, 3...)Dải số (0..1, 1..n)Bất kỳ giá trị nào: *Không ghi: mặc định là 1Ví dụ Lớp ToaDoDiemVí dụ Lớp ToaDoDiem (tt)Ví dụ Lớp TamGiacVí dụ Lớp TamGiac (tt)Bài tập 1Xây dựng một trò chơi xúc xắc. Cách chơi như sau:Mỗi hạt xúc xắc được gieo sẽ có giá trị ngẫu nhiên 1..6Hai người lần lượt gieo 1 hạt xúc xắcSau mỗi lượt gieo, số điểm của lượt đó được tích lũy vào số điểm của người chơiSau các lượt gieo theo quy định, người thắng cuộc là người có tổng số điểm lớn hơnHãy xác định các lớp cần thiết và cài đặt Xác định lớpXúc xắc (XucXac)Thuộc tính: giá trị của mặt (giaTri)Phương thức: sinh ngẫu nhiên giá trị mặt của xúc xắc (sinhGiaTri())Người chơi (NguoiChoi)Thuộc tính: tên (ten), điểm (diem)Phương thức: gieo xúc xắc (gieoXucXac())Xác định lớpTrận đấu (TranDau)Thuộc tính: xúc xắc (xucXac), 2 người chơi (nguoiChoi), số vòng chơi (soVong), người thắng cuộc (nguoiThang)Phương thức: bắt đầu (batDau()), kết thúc (ketThuc), hiển thị thông tin (hienThi()), thực hiện trận đấu (thucHienTranDau())Xác định lớpLớp XucXacpublic class XucXac { private int giaTri; public int getGiaTri() { return giaTri; } public void setGiaTri(int giaTri) { this.giaTri = giaTri; } public XucXac(){ giaTri=1; } public void sinhGiaTri(){ Random random = new Random(); this.giaTri=random.nextInt(5) + 1; } }Lớp NguoiChoipublic class NguoiChoi { private String ten; private int diem; public String getTen() { return ten; } public void setTen(String ten) { this.ten = ten; } public int getDiem() { return diem; } public void setDiem(int diem) { this.diem = diem; }Lớp NguoiChoi public NguoiChoi(String ten){ this.ten=ten; this.diem=0; } public void gieoXucXac(XucXac xucXac){ Scanner sn = new Scanner(System.in); System.out.print(">>> Hay nhan Enter de gieo xuc xac..."); sn.nextLine(); xucXac.sinhGiaTri(); this.diem+=xucXac.getGiaTri(); System.out.println("-- Diem: " + this.diem); } }Lớp TranDaupublic class TranDau { private XucXac xucXac; private NguoiChoi nguoiChoi1; private NguoiChoi nguoiChoi2; private NguoiChoi nguoiThang; private int soVong; public TranDau(String ten1, String ten2, int soVong){ this.nguoiChoi1 = new NguoiChoi(ten1); this.nguoiChoi2 = new NguoiChoi(ten2); this.xucXac = new XucXac(); this.soVong = soVong; }Lớp TranDaupublic void batDau(){ System.out.println("Tran dau bat dau..."); for(int i=1; i" + nguoiChoi1.getTen() + " gieo xuc xac"); nguoiChoi1.gieoXucXac(xucXac); System.out.println(">" + nguoiChoi2.getTen() + " gieo xuc xac"); nguoiChoi2.gieoXucXac(xucXac); } } Lớp TranDau public void ketThuc(){ int diem1= nguoiChoi1.getDiem(); int diem2=nguoiChoi2.getDiem(); if(diem1>diem2) this.nguoiThang=this.nguoiChoi1; else if(diem2>diem1) this.nguoiThang=this.nguoiChoi2; }Lớp TranDau public void hienThi(){ System.out.println("* Ket qua tran dau *"); System.out.printf("- Diem cua %s: %d", nguoiChoi1.getTen(), nguoiChoi1.getDiem()); System.out.printf("- Diem cua %s: %d", nguoiChoi2.getTen(), nguoiChoi2.getDiem()); if(nguoiThang!=null) System.out.printf("Nguoi thang cuoc: %s", nguoiThang.getTen()); else System.out.println("Tran dau hoa!!!"); } public void thucHienTranDau(){ batDau(); ketThuc(); hienThi(); } }public class XucXacTest { public static void main(String []args){ String ten1, ten2; int soVong; Scanner sn = new Scanner(System.in); System.out.print("> Ten nguoi choi 1: "); ten1=sn.nextLine(); System.out.print("> Ten nguoi choi 2: "); ten2=sn.nextLine(); System.out.print("> So vong dau: "); soVong=sn.nextInt(); TranDau tranDau = new TranDau(ten1, ten2, soVong); tranDau.thucHienTranDau(); } }Bài tập 2Hãy viết lại các lớp trong Bài tập 1 để thoả yêu cầu sau:Có thêm thuộc tính soBanThang ghi lại số bàn thắngGiả sử 2 người chơi phải chơi 3 ván đấu. Nếu người chơi nào thắng trước 2 ván thì người chơi đó thắng cả trận đấuKế thừa (Inheritance)Ngoài việc nhóm các đối tượng có cùng tập thuộc tính/hành vi lại với nhau thành một lớp, con người thường nhóm các đối tượng có cùng một số thuộc tính/ hành viVí dụ: nhóm tất cả xe chạy bằng động cơ thành một nhóm, rồi phân thành các nhóm nhỏ hơn tuỳ theo loại xe (xe ô tô, xe tải, ...)Kế thừaMỗi nhóm con là một lớp các đối tượng tương tự, nhưng giữa các nhóm con có chung một số đặc điểmQuan hệ giữa các nhóm con với nhóm lớn được gọi là quan hệ “là một” (is-a)Kế thừaVí dụ:Một cái xe ô tô “là một” xe động cơMột cái xe tải “là một” xe động cơMột cái xe máy “là một” xe động cơ Dùng cấu trúc hướng đối tượng để định nghĩa quan hệ “là một”Kế thừaCác đối tượng được nhóm lại thành một lớp thì có cùng tập thuộc tính và hành viMọi đối tượng xe động cơ có cùng tập thuộc tính và hành vi Mọi đối tượng xe tải có cùng tập thuộc tính và hành viKế thừaMối liên kết giữa các lớp trong quan hệ “là một” xuất phát từ thực tế rằng:Các lớp con cũng có mọi thuộc tính/ hành vi của lớp chavà cộng thêm các thuộc tính/ hành vi khácKế thừaLớp cha – superclass (hoặc lớp cơ sở - base class)Lớp tổng quát hơn trong mối quan hệ “là một”Các đối tượng thuộc lớp cha có cùng tập thuộc tính và hành viKế thừaLớp con – subclass (hoặc lớp dẫn xuất – derived class)Lớp cụ thể hơn trong một quan hệ “là một”Các đối tượng thuộc lớp con có cùng tập thuộc tính và hành vi (do kế thừa từ lớp cha), kèm thêm tập thuộc tính và hành vi của riêng lớp conKế thừaQuan hệ “là một” còn gọi là sự kế thừa (inheritance)Ta nói rằng lớp con “kế thừa từ” lớp cha, hoặc lớp con “được dẫn xuất từ” lớp cha  Kế thừa là quá trình tạo nên lớp mới bằng cách dẫn xuất từ lớp cũKế thừaƯu điểm của việc kế thừaTiết kiệm thời gian và công sứcTái sử dụng lại những lớp có sẵnGiảm lượng code phải thiết kế, viết, kiểm traTránh trùng lắp codeRút ngắn thời gian giúp LTV tập trung vào mục tiêuGiúp phân loại và thiết kế lớp dễ dàng, dễ quản lýKế thừaPhân loạiĐơn kế thừa (single inheritance): chỉ có một lớp chaĐa kế thừa (multiple inheritance): có nhiều lớp chaKế thừaTạo lớp mới bằng cách phát triển từ lớp đã cóLớp mới kế thừa những thành viên đã có trong lớp cũLớp cũ: Lớp cha (superclass), lớp cơ sở (baseclass)Lớp mới: Lớp con (subclass), lớp dẫn xuất (derived class)Ví dụ:Lớp cũ: Điểm (ToaDoDiem)Kết hợp: Tam giác (TamGiac) có 3 điểmKế thừa: Tam giác vuông (TamGiacVuong)Kết hợp vs Kế thừaKế thừaKết hợpTái sử dụng mã nguồnthông qua lớpTái sử dụng mã nguồnthông qua đối tượngQuan hệ “là một loại” Quan hệ “là một phần”Ví dụ: Tam giác vuông là một loại tam giácVí dụ: Tam giác có 3 đỉnhKý hiệu kế thừaSơ đồ quan hệ đối tượng (Object Relationship Diagram – ORD)Thể hiệnSự khác nhau giữa lớp cơ sở và lớp dẫn xuấtSự khác nhau giữa các lớp dẫn xuấtSơ đồ quan hệ đối tượngĐối với những lớp dẫn xuất, chỉ cần liệt kê các thuộc tính/ hành vi mà lớp cơ sở không có Đơn giản hoá sơ đồNhấn mạnh các điểm khác biệtCây kế thừaCác quan hệ kế thừa luôn được biểu diễn với các lớp dẫn xuất đặt dưới lớp cơ sở để nhấn mạnh bản chất phả hệ của quan hệCây kế thừaKế thừa phần lớn các thành viên dữ liệu và phương thức của lớp cơ sở Lớp dẫn xuấtCó thể bổ sung thêm các thành viên dữ liệu mới và các phương thức mới (ngoại trừ constructor, destructor)Lớp cơ sở trực tiếpLớp cơ sởLớp cơ sở gián tiếpClass AClass BClass CNhận biết kế thừa?class Aclass Bclass ABclass Aclass BĐịnh nghĩa lớp kế thừaCú phápclass SubClass extends SuperClass{ Định nghĩa SubClass}Lớp con truy cập tới thành viên lớp cha qua từ khóa superMọi lớp trong Java đều kế thừa từ lớp tổng quát ObjectLớp Object cung cấp một số phương thức toString(), equals()Java chỉ cho phép đơn kết thừa: một lớp chỉ có thể kế thừa từ duy nhất 1 lớp khácChỉ định truy cậpChỉ định truy cập lớp:public: cho phép lớp con kế thừa nằm ở bất kỳ đâuKhông chỉ định: chỉ cho phép lớp con kế thừa nằm cùng góiChỉ định truy cập thành viên:public, protected: cho phép lớp con ở bất kỳ đâu được kế thừa thuộc tính/phương thức này, được truy cập vào thuộc tính/thành viên tương ứng trên lớp chaKhông chỉ định: chỉ cho phép lớp con ở cùng gói được kế thừa và được truy cập tới thuộc tính/thành viên tương ứng của lớp chaprivate: lớp con không được kế thừa thuộc tính/phương thức này, không được truy cập vào thuộc tính/thành viên tương ứng trên lớp chaVí dụ chỉ định public cho class chaVí dụ class con cùng góiVí dụ class con khác góiVí dụ không chỉ định public class chaCùng gói: tương tự chỉ định publicKhác gói: không cho kế thừa!!!Khởi tạo đối tượng trong kế thừaLớp con không kế thừa phương thức khởi tạo của lớp chaLớp cha phải được khởi tạo trước lớp conCác phương thức khởi tạo của lớp con tự động gọi phương thức khởi tạo mặc định của lớp cha (nếu có) Nếu lớp cha không có phương thức khởi tạo mặc định thì phải gọi phương thức khởi tạo khác mặc định của lớp chaCú pháp: super(parameterList)Thứ tự khởi tạo và huỷ trong kế thừaABCVí dụ khởi tạo đối tượng trong kế thừaVí dụ khởi tạo đối tượng trong kế thừaVí dụ khởi tạo đối tượng trong kế thừa (tt)Ví dụ khởi tạo đối tượng trong kế thừa (tt)Đối tượng cha và conKhi tạo đối tượng con, đối tượng cha được tạo ra độc lậpĐối tượng con có tham chiếu tới đối tượng cha qua từ khóa super (tham chiếu này là private)Trong lớp con, nếu truy cập tới thuộc tính/phương thức của cha thì truy cập đó có được là qua từ khóa super (tường minh, hoặc không tường minh), đối tượng con được xem như đối tượng thuộc lớp cha (upcasting)Ví dụThiết kế các lớp cần thiết để quản lý thông tin của một giảng viên và sinh viên.Đối với sinh viên gồm các thông tin và hành vi:Họ tênTuổiTên trường họcSố tín chỉ đã tích luỹCập nhật số tín chỉHiển thị thông tinVí dụ (tt)Đối với giảng viên gồm các thông tin và hành vi:Họ tênTuổiTên trường công tácHọc vịHệ số lươngMức lương cơ bảnGiả sử không dùng kế thừaLớp SinhVienpublic class SinhVienKhongKeThua { private String hoTen; private int tuoi; private String tenTruong; private int tinChiTichLuy; public String getHoTen() { return hoTen; } public void setHoTen(String hoTen) { this.hoTen = hoTen; } public int getTuoi() { return tuoi; } public void setTuoi(int tuoi) { this.tuoi = tuoi; }public String getTenTruong() { return tenTruong; } public void setTenTruong(String tenTruong) { this.tenTruong = tenTruong; } public int getTinChiTichLuy() { return tinChiTichLuy; } public void setTinChiTichLuy(int tinChiTichLuy) { this.tinChiTichLuy = tinChiTichLuy; } public SinhVienKhongKeThua(String hoTen, int tuoi, String tenTruong) { this.setHoTen(hoTen); this.setTuoi(tuoi); this.setTenTruong(tenTruong); this.setTinChiTichLuy(0); } public void capNhatTinChi(int soLuong){ this.setTinChiTichLuy(this.getTinChiTichLuy() + soLuong); } public void hienThiThongTinSinhVien() { System.out.println("- Ho va ten: " + this.getHoTen()); System.out.println("- Tuoi: " + this.getTuoi()); System.out.println("- Ten truong: " + this.getTenTruong()); System.out.println("- So tin chi tich luy: " + this.getTinChiTichLuy()); } }Lớp GiangVienpublic class GiangVienKhongKeThua { private String hoTen; private int tuoi; private String tenTruong; private String hocVi; private double heSoLuong; private int luongCoBan; public String getHoTen() { return hoTen; } public void setHoTen(String hoTen) { this.hoTen = hoTen; } public int getTuoi() { return tuoi; }public String getTenTruong() { return tenTruong; } public void setTenTruong(String tenTruong) { this.tenTruong = tenTruong; } public String getHocVi() { return hocVi; } public void setHocVi(String hocVi) { this.hocVi = hocVi; } public double getHeSoLuong() { return heSoLuong; } public void setHeSoLuong(double heSoLuong) { this.heSoLuong = heSoLuong; }public int getLuongCoBan() { return luongCoBan; } public void setLuongCoBan(int luongCoBan) { this.luongCoBan = luongCoBan; } public GiangVienKhongKeThua(String hoTen, int tuoi, String tenTruong, String hocVi, int heSoLuong, int luongCoBan){ this.setHoTen(hoTen); this.setTuoi(tuoi); this.setTenTruong(tenTruong); this.setHocVi(hocVi); this.setHeSoLuong(heSoLuong); this.setLuongCoBan(luongCoBan); } public void hienThiThongTinGiangVien(){ System.out.println("- Ho va ten: " + this.getHoTen()); System.out.println("- Tuoi: " + this.getTuoi()); System.out.println("- Ten truong: " + this.getTenTruong()); System.out.println("- Hoc vi: " + this.getHocVi()); System.out.println("- He so luong: " + this.getHeSoLuong()); System.out.println("- Luong co ban: " + this.getLuongCoBan()); } }Sử dụng lớp kế thừaSử dụng lớp kế thừaTách những thông tin chung thành 1 lớp mới: Lớp người (ConNguoi) gồm các thông tin và hành vi nói chungTênTuổiNghề nghiệpHiển thị thông tinCây kế thừaLớp ConNguoipublic class ConNguoi { private String hoTen; private int tuoi; private String tenTruong; private String ngheNghiep; public String getHoTen() { return hoTen; } public void setHoTen(String hoTen) { this.hoTen = hoTen; } public int getTuoi() { return tuoi; } public void setTuoi(int tuoi) { this.tuoi = tuoi; }public String getNgheNghiep() { return ngheNghiep; } public void setNgheNghiep(String ngheNghiep) { this.ngheNghiep = ngheNghiep; } public String getTenTruong() { return tenTruong; } public void setTenTruong(String tenTruong) { this.tenTruong = tenTruong; } public ConNguoi(String hoTen, int tuoi, String tenTruong) { this.setHoTen(hoTen); this.setTuoi(tuoi); this.setTenTruong(tenTruong); this.setNgheNghiep(""); } public void hienThiThongTinNguoi() { System.out.println("- Ho va ten: " + this.getHoTen()); System.out.println("- Tuoi: " + this.getTuoi()); System.out.println("- Nghe nghiep: " + this.getNgheNghiep()); System.out.println("- Ten truong: " + this.getTenTruong()); }Lớp SinhVienpublic class SinhVien extends ConNguoi{ private int tinChiTichLuy; public int getTinChiTichLuy() { return tinChiTichLuy; } public void setTinChiTichLuy(int tinChiTichLuy){ this.tinChiTichLuy = tinChiTichLuy; } public SinhVien(String hoTen, int tuoi, String tenTruong) { super(hoTen, tuoi, tenTruong); super.setNgheNghiep("Sinh vien"); this.setTinChiTichLuy(0); } public void capNhatTinChi(int soLuong) { this.setTinChiTichLuy(this.getTinChiTichLuy() + soLuong); } public void hienThiThongTinSinhVien() { super.hienThiThongTinNguoi(); System.out.println("- So tin chi da tich luy: " + this.getTinChiTichLuy()); }public class SinhVienTest { public static void main(String []args) { System.out.println("*** Tao doi tuong con nguoi:"); ConNguoi nguoi = new ConNguoi("An", 17, ""); System.out.println("*** Thong tin vua tao:"); nguoi.hienThiThongTinNguoi(); System.out.println("*** An tro thanh sinh vien DH ABC:"); SinhVien sv = new SinhVien(nguoi.getHoTen(), nguoi.getTuoi(), "Dai hoc ABC"); System.out.println("*** Thong tin sinh vien:"); sv.hienThiThongTinSinhVien(); System.out.println("*** An hoc xong mon OOP in Java (4 tin chi)"); System.out.println("*** Cap nhat so tin chi cho An:"); sv.capNhatTinChi(4); System.out.println("*** Thong tin sinh vien:"); sv.hienThiThongTinSinhVien(); } }!!! Tương tự cho lớp GiangVienChe thuộc tínhTrong lớp con khai báo một thuộc tính có tên giống lớp cha thì trong lớp con thuộc tính của lớp cha bị che điĐể truy cập tới thuộc tính trên lớp cha dùng từ khóa superĐể phân biệt trong lớp con, dùng từ khóa thisVí dụVí dụNạp chồng và ghi đè phương thứcLớp con có thể định nghĩa lại các phương thức kế thừa được từ lớp cha:Ghi đè (overriding): Cùng mẫu với phương thức của lớp cha Nạp chồng phương thức (overloading): Giữ nguyên tên phương thức và thay đổi danh sách tham số!!! Giữ nguyên kiểu dữ liệu trả về của lớp chaVí dụ 1Ví dụ 1 (tt)Ví dụ 2Ví dụ 2 (tt)Cấm ghi đè phương thứcTrong một số trường hợp cần cấm ghi đè phương thức khi kế thừa:Đảm bảo tính đúng đắn: việc ghi đè phương thức có thể gây ra sự sai lạc về ý nghĩaTính hiệu quả: giảm thời gian xử lý lời gọi phương thức định nghĩa phương thức với từ khóa finalVí dụLỗiTính đa hình trong JavaTính đa hình trong JavaTrừu tượng hoáHiện thực đa hình trong JavaTrừu tượng hoáLoại bỏ những thông tin cụ thể, giữ lại các thông tin chungMức độ trừu tượng hoá được thể hiện trên cây kế thừaĐịnh nghĩa lớp trừu tượngSử dụng từ khoá abstract cho phương thức trừu tượngBổ sung từ khoá abstract phía trước classpublic abstract class ClassName{ Khai báo thuộc tính; public abstract dataType methodName(listParameter); Định nghĩa các phương thức khác; }Đặc điểm lớp trừu tượngPhương thức trừu tượng không được phép định nghĩa cụ thể tại lớp cha (kết thúc khai báo phương thức bằng dấu ;)Lớp con kế thừa từ lớp trừu tượng phải định nghĩa nội dung của phương thức trừu tượngChỉ định truy cập không được chặt hơn lớp chaKhông được tạo đối tượng từ lớp trừu tượngLớp trừu tượng vẫn có phương thức khởi tạoVí dụCho lớp hình tròn (HinhTron) gồm:Toạ độ tâm: x, yBán kính: banKinhTính diện tính: tinhDienTich()Cho lớp hình chữ nhật (HinhChuNhat) gồm:Toạ độ tâm: x, yKích thước: chieuNgang, chieuDungTính diện tích: tinhDienTich()2 lớp cùng chung: x, y, tinhDienTich()Ví dụ (tt)Công thức tinhDienTich() chung cho cả hình tròn và hình chữ nhật: rỗng  phương thức trừu tượng public abstract double tinhDienTich();Lớp trừu tượngpublic abstract class HinhHocVí dụ (tt)Lớp HinhHocLớp HinhTronLớp HinhChuNhatLớp HinhHocTestGiao diện (Interface)Giao diệnSử dụng trong trường hợp đa kế thừa (kế thừa từ nhiều lớp)Giao diện chỉ quy định các phương thức phải có, nhưng không định nghĩa cụ thểTách rời đặc tả mức trừu tượng và triển khai cụ thểĐảm bảo tính cộng tác trong phát triển phần mềmCác giao diện có thể kế thừa nhau• Cú pháp11Modifier interface InterfaceName {//Declare constants//Declare methods}Giao diệnCú phápModifier interface InterfaceName { Khai báo các hằng số Khai báo các phương thức }Triển khai giao diệnModifier class ClassName implements Interface1, Interface2 { 1. Định nghĩa lớp 2. Định nghĩa tất cả các phương thức của Interface1 và Interface2 }Kế thừa và triển khai giao diệnModifier class SubClass extends SuperClass implements Interface1, Interface2 { Định nghĩa SubClass kế thừa từ SuperClass Định nghĩa tất cả phương thức của Interface1 và Interface2 }Giao diện vs Trừu tượngGiao diệnTrừu tượngChỉ được phép có thành viên hằngCó thể có thuộc tínhMọi phương thức là trừu tượng với chỉ định truy cập publicNgoài phương thức trừu tượng, có thể có phương thức riêngKhông có phương thức khởi tạoCó phương thức khởi tạoMột lớp có thể triển khai nhiều giao diệnMột lớp chỉ có thể kế thừa từ một lớp trừu tượngKhông tái sử dụng mã nguồnCó tái sử dụng mã nguồnVí dụGiao diện HinhHocLớp HinhTronLớp HinhChuNhatĐa hình (Polymorphism)Nhiều hình thức thực hiện một hành vi, nhiều kiểu tồn tại của một đối tượngĐa hình phương thức: chồng phương thức, ghi đè phương thứcĐa hình đối tượng: nhìn nhận đối tượng theo nhiều kiểu khác nhauUpcasting và DowncastingUpcasting: đối tượng lớp con được nhìn nhận như đối tượng lớp cha: Thực hiện tự độngDowncasting: đối tượng lớp cha được nhìn nhận như đối tượng lớp con: Phải ép kiểuVí dụToán tử instanceofKiểm tra một đối tượng có phải đang là thể hiện của lớp hoặc giao diện nào đó không: true h