1. Trang chủ
  2. » Công Nghệ Thông Tin

Giáo trình môn học Lập trình hướng đối tượng: Phần 1

142 16 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 142
Dung lượng 3,46 MB

Nội dung

Giáo trình này cung cấp cho sinh viên các kiến thức từ cơ bản cho đến một số kỹ thuật nâng cao về phương pháp lập trình hướng đối tượng. Giáo trình gồm có 2 phần với 13 chương, phần 1 giáo trình gồm có những nội dung: Mở đầu, ngôn ngữ lập trình java, lớp và đối tượng, biến và các kiểu dữ liệu, hành vi của đối tượng, sử dụng thư viện java, thừa kế và đa hình, lớp trừu tượng và interface.

Mục lục GIỚI THIỆU .5 Chương MỞ ĐẦU 1.1 KHÁI NIỆM CƠ BẢN 12 1.2 ĐỐI TƯỢNG VÀ LỚP 13 1.3 CÁC NGUYÊN TẮC TRỤ CỘT 15 Chương NGƠN NGỮ LẬP TRÌNH JAVA 20 2.1 ĐẶC TÍNH CỦA JAVA 20 2.1.1 Máy ảo Java – Java Virtual Machine .21 2.1.2 Các tảng Java .23 2.1.3 Mơi trường lập trình Java 23 2.1.4 Cấu trúc mã nguồn Java 24 2.1.5 Chương trình Java .25 2.2 BIẾN .27 2.3 CÁC PHÉP TOÁN CƠ BẢN 28 2.3.1 Phép gán 28 2.3.2 Các phép toán số học 28 2.3.3 Các phép toán khác 29 2.3.4 Độ ưu tiên phép toán 30 2.4 CÁC CẤU TRÚC ĐIỀU KHIỂN 30 2.4.1 Các cấu trúc rẽ nhánh .31 2.4.2 Các cấu trúc lặp 37 2.4.3 Biểu thức điều kiện cấu trúc điều khiển 43 Chương LỚP VÀ ĐỐI TƯỢNG 48 3.1 TẠO VÀ SỬ DỤNG ĐỐI TƯỢNG 49 3.2 TƯƠNG TÁC GIỮA CÁC ĐỐI TƯỢNG 51 Chương BIẾN VÀ CÁC KIỂU DỮ LIỆU 57 4.1 BIẾN VÀ CÁC KIỂU DỮ LIỆU CƠ BẢN 58 4.2 THAM CHIẾU ĐỐI TƯỢNG VÀ ĐỐI TƯỢNG 59 4.3 PHÉP GÁN 62 4.4 CÁC PHÉP SO SÁNH 63 4.5 MẢNG 64 Chương HÀNH VI CỦA ĐỐI TƯỢNG .70 5.1 PHƯƠNG THỨC VÀ TRẠNG THÁI ĐỐI TƯỢNG70 5.2 TRUYỀN THAM SỐ VÀ GIÁ TRỊ TRẢ VỀ 71 5.3 CƠ CHẾ TRUYỀN BẰNG GIÁ TRỊ 73 5.4 ĐÓNG GÓI VÀ CÁC PHƯƠNG THỨC TRUY NHẬP 5.5 KHAI BÁO VÀ KHỞI TẠO BIẾN THỰC THỂ 79 5.6 BIẾN THỰC THỂ VÀ BIẾN ĐỊA PHƯƠNG 80 Chương SỬ DỤNG THƯ VIỆN JAVA 85 6.1 ArrayList .85 6.2 SỬ DỤNG JAVA API 87 6.3 MỘT SỐ LỚP THÔNG DỤNG TRONG API 88 6.3.1 Math 88 6.3.2 Các lớp bọc kiểu liệu 89 6.3.3 Các lớp biểu diễn xâu kí tự 90 6.4 TRỊ CHƠI BẮN TÀU 91 Chương THỪA KẾ VÀ ĐA HÌNH 103 7.1 QUAN HỆ THỪA KẾ 103 7.2 THIẾT KẾ CÂY THỪA KẾ 104 7.3 CÀI ĐÈ – PHƯƠNG THỨC NÀO ĐƯỢC GỌI? 107 7.4 CÁC QUAN HỆ IS-A VÀ HAS-A 108 7.5 KHI NÀO NÊN DÙNG QUAN HỆ THỪA KẾ? 110 7.6 LỢI ÍCH CỦA QUAN HỆ THỪA KẾ 110 7.7 ĐA HÌNH 111 7.8 GỌI PHIÊN BẢN PHƯƠNG THỨC CỦA LỚP CHA114 7.9 CÁC QUY TẮC CHO VIỆC CÀI ĐÈ 115 7.10 CHỒNG PHƯƠNG THỨC 116 7.11 CÁC MỨC TRUY NHẬP 117 Chương LỚP TRỪU TƯỢNG VÀ INTERFACE 124 8.1 MỘT SỐ LỚP KHÔNG NÊN TẠO THỰC THỂ 124 8.2 LỚP TRỪU TƯỢNG VÀ LỚP CỤ THỂ 126 75 8.3 PHƯƠNG THỨC TRỪU TƯỢNG 127 8.4 VÍ DỤ VỀ ĐA HÌNH 127 8.5 LỚP Object 131 8.6 ĐỔI KIỂU – KHI ĐỐI TƯỢNG MẤT HÀNH VI CỦA MÌNH 132 8.7 ĐA THỪA KẾ VÀ VẤN ĐỀ HÌNH THOI 135 8.8 INTERFACE 137 Chương VÒNG ĐỜI CỦA ĐỐI TƯỢNG 143 9.1 BỘ NHỚ STACK VÀ BỘ NHỚ HEAP 143 9.2 KHỞI TẠO ĐỐI TƯỢNG 145 9.3 HÀM KHỞI TẠO VÀ VẤN ĐỀ THỪA KẾ 149 9.3.1 Gọi hàm khởi tạo lớp cha 150 9.3.2 Truyền đối số cho hàm khởi tạo lớp cha 152 9.4 HÀM KHỞI TẠO CHỒNG NHAU 153 9.5 TẠO BẢN SAO CỦA ĐỐI TƯỢNG 154 9.6 CUỘC ĐỜI CỦA ĐỐI TƯỢNG 159 Chương 10 THÀNH VIÊN LỚP VÀ THÀNH VIÊN THỰC THỂ 164 10.1 BIẾN CỦA LỚP 164 10.2 PHƯƠNG THỨC CỦA LỚP 165 10.3 GIỚI HẠN CỦA PHƯƠNG THỨC LỚP 167 10.4 KHỞI TẠO BIẾN LỚP 169 10.5 MẪU THIẾT KẾ SINGLETON 170 10.6 THÀNH VIÊN BẤT BIẾN – final 171 Chương 11 NGOẠI LỆ 174 11.1 NGOẠI LỆ LÀ GÌ? 175 11.1.1 Tình cố 175 11.1.2 Xử lý ngoại lệ 177 11.1.3 Ngoại lệ đối tượng 178 11.2 KHỐI try/catch 179 11.2.1 Bắt nhiều ngoại lệ 179 11.2.2 Hoạt động khối try/catch 180 11.2.3 Khối finally – việc dù phải làm 182 11.2.4 Thứ tự cho khối catch 183 11.3 NÉM NGOẠI LỆ 184 11.4 NÉ NGOẠI LỆ 185 11.5 NGOẠI LỆ ĐƯỢC KIỂM TRA VÀ KHÔNG ĐƯỢC KIỂM TRA 189 11.6 ĐỊNH NGHĨA KIỂU NGOẠI LỆ MỚI 190 11.7 NGOẠI LỆ VÀ CÁC PHƯƠNG THỨC CÀI ĐÈ 191 Chương 12 CHUỖI HÓA ĐỐI TƯỢNG VÀ VÀO RA FILE 196 12.1 QUY TRÌNH GHI ĐỐI TƯỢNG 197 12.2 CHUỖI HÓA ĐỐI TƯỢNG 199 12.3 KHÔI PHỤC ĐỐI TƯỢNG 202 12.4 GHI CHUỖI KÍ TỰ RA TỆP VĂN BẢN 205 12.4.1 Lớp File 206 12.4.2 Bộ nhớ đệm 207 12.5 ĐỌC TỆP VĂN BẢN 207 12.6 CÁC DÒNG VÀO/RA TRONG Java API 209 Chương 13 LẬP TRÌNH TỔNG QUÁT VÀ CÁC LỚP COLLECTION 13.1 LỚP TỔNG QUÁT 217 13.2 PHƯƠNG THỨC TỔNG QUÁT 219 13.3 CÁC CẤU TRÚC DỮ LIỆU TỔNG QUÁT TRONG JAVA API 220 13.4 ITERATOR VÀ VÒNG LẶP FOR EACH 222 13.5 SO SÁNH NỘI DUNG ĐỐI TƯỢNG 224 13.5.1 So sánh 224 13.5.2 So sánh lớn hơn/nhỏ 226 13.6 KÍ TỰ ĐẠI DIỆN TRONG KHAI BÁO THAM SỐ KIỂU 228 Phụ lục A DỊCH CHƯƠNG TRÌNH BẰNG JDK 233 Phụ lục B PACKAGE – TỔ CHỨC GÓI CỦA JAVA 236 Phụ lục C BẢNG THUẬT NGỮ ANH-VIỆT 239 Tµi liƯu tham kh¶o 241 215 Giíi thiƯu Phần mềm ngày lớn phức tạp đòi hỏi cập nhật liên tục để đáp ứng yêu cầu người dùng Phương pháp lập trình thủ tục truyền thống dần trở nên khơng đáp ứng địi hỏi ngành cơng nghiệp phần mềm Lập trình hướng đối tượng đời bối cảnh để hỗ trợ sử dụng lại phát triển phần mềm qui mơ lớn Giáo trình cung cấp cho sinh viên kiến thức từ số kỹ thuật nâng cao phương pháp lập trình hướng đối tượng Giáo trình dùng cho sinh viên ngành Cơng nghệ thơng tin có kiến thức lập trình Giáo trình sử dụng ngơn ngữ lập trình Java để minh họa đồng thời giới thiệu số kiến thức ngôn ngữ Các nội dung phương pháp lập trình hướng đối tượng trình bày giáo trình bao gồm lớp đối tượng, đóng gói/che giấu thơng tin, kế thừa đa hình, xử lý ngoại lệ lập trình tổng qt Ngồi ra, giáo trình trình bày kiến thức Java bao gồm đặc trưng ngôn ngữ, thư viện cách thức tổ chức vào/ra liệu Thay cách trình bày theo tính hàn lâm chủ đề rộng, để thuận tiện cho giảng dạy, giáo trình chọn cách trình bày theo học cụ thể xếp theo trình tự kiến thức từ sở đến chuyên sâu Mỗi chủ đề giảng dạy với thời lượng 2~3 lý thuyết thực hành tương ứng Ch-¬ng Ch-¬ng 6, với nội dung kiến thức ngơn ngữ lập trình Java, cần thiết nội dung trọng tâm môn học Lập trình hướng đối tượng Các chương này, đó, nên để sinh viên tự học Chương Chương 10 không thiết phải dạy thành chủ đề độc lập mà tách rải rác nội dung kiến thức giới thiệu kèm theo khái niệm hướng đối tượng có liên quan, yêu cầu sinh viên tự đọc cần đến kiến thức trình thực hành Tuy giáo trình khơng trình bày sâu lập trình Java, kiến thức lập trình Java lại cần thiết sinh viên, với mục đích thực hành mơn học Do đó, ngồi mục đích thực hành nội dung liên quan đến lập trình hướng đối tượng, tập thực hành môn học nên có thêm đóng vai trị định hướng gợi ý giúp đỡ sinh viên tự học chủ đề túy Java mà giáo viên cho cần thiết, chẳng hạn học vào liệu đơn giản từ tuần môn học Các định hướng thể tập thực hành với đoạn chương trình mẫu, yêu cầu tìm hiểu tài liệu API số lớp tiện ích Một số tập cuối chương ví dụ dạng tập Các thuật ngữ hướng đối tượng nguyên gốc tiếng Anh chuyển sang tiếng Việt theo cách khác tùy tác giả Sinh viên cần biết thuật ngữ nguyên gốc tiếng Anh cách dịch khác để tiện cho việc sử dụng tài liệu tiếng Anh để liên hệ kiến thức tài liệu tiếng Việt Vì lí đó, giáo trình cung cấp bảng thuật ngữ Anh-Việt với cách dịch khác Phụ lục C, bên cạnh Phụ lục A cơng cụ lập trình JDK Phụ lục B tổ chức gói ngơn ngữ Java Các tác giả chân thành cảm ơn PGS TS Nguyễn Đình Hóa, TS Trương Anh Hồng, TS Cao Tuấn Dũng, TS Đặng Đức Hạnh, đồng nghiệp sinh viên Khoa Công nghệ thông tin, Trường Đại học Công nghệ đọc thảo giáo trình có góp ý q báu nội dung chun mơn cách thức trình bày Tuy vậy, giáo trình cịn nhiều khiếm khuyết, tác giả mong tiếp tục nhận góp ý để hồn thin tng lai Chơng mở đầu Lp trình cơng đoạn quan trọng chủ chốt khơng thể thiếu để tạo sản phẩm phần mềm Phần mềm trở nên đa dạng ngành công nghiệp phần mềm phát triển người ta thấy rõ tầm quan trọng phương pháp lập trình Phương pháp lập trình tốt khơng đảm bảo tạo phần mềm tốt mà hỗ trợ thiết kế phần mềm có tính mở hỗ trợ khả sử dụng lại mơ đun Nhờ dễ dàng bảo trì, nâng cấp phần mềm giảm chi phí phát triển phần mềm Trong thập kỷ 1970, 1980, phương pháp phát triển phần mềm chủ yếu lập trình có cấu trúc (structured programming) Cách tiếp cận cấu trúc việc thiết kế chương trình dựa chiến lược chia để trị: Để giải tốn lớn, tìm cách chia thành vài tốn nhỏ giải riêng bài; để giải bài, coi tốn tiếp tục chia thành tốn nhỏ hơn; cuối cùng, ta đến tốn giải mà không cần phải chia tiếp Cách tiếp cận gọi lập trình từ xuống (top-down programming) Lập trình từ xuống phương pháp tốt áp dụng thành công cho phát triển nhiều phần mềm Tuy nhiên, với đa dạng phức tạp phần mềm, phương pháp bộc lộ hạn chế Trước hết, đáp ứng việc tạo lệnh quy trình để giải tốn Dần dần, người ta nhận thiết kế cấu trúc liệu cho chương trình có tầm quan trọng không việc thiết kế hàm/thủ tục cấu trúc điều khiển Lập trình từ xuống không quan tâm đủ đến liệu mà chương trình cần xử lý Thứ hai, với lập trình từ xuống, khó tái sử dụng phần chương trình cho chương trình khác Bằng việc xuất phát từ toán cụ thể chia thành mảnh cho thuận, cách tiếp cận có xu hướng tạo thiết kế đặc thù cho tốn Chúng ta khó có khả lấy đoạn mã lớn từ chương trình cũ lắp vào dự án mà sửa đổi lớn Việc xây dựng chương trình chất lượng cao khó khăn tốn kém, nhà phát triển phần mềm luôn muốn tái sử dụng sản phẩm cũ Thứ ba, môi trường hoạt động thực tế ứng dụng thay đổi Dẫn đến việc yêu cầu phần mềm phải liên tục thay đổi theo để đáp ứng nhu cầu người dùng không muốn phần mềm bị đào thải Do đó, thiết kế linh hoạt mềm dẻo mà nhà phát triển phần mềm mong muốn Phương pháp tiếp cận từ lên (bottom-up) hỗ trợ tốt cho tính linh hoạt mềm dẻo Trong thực tế, thiết kế lập trình từ xuống thường kết hợp với thiết kế lập trình từ lên Trong tiếp cận từ lên, từ vấn đề mà ta biết cách giải có sẵn thành phần tái sử dụng xây dựng dần theo hướng lên trên, hướng đến giải pháp cho toán tổng Các thành phần tái sử dụng nên có tính mơ-đun hóa cao Mỗi mơ-đun thành phần hệ thống lớn hơn, tương tác với phần lại hệ thống theo cách đơn giản quy ước chặt chẽ Ý tưởng mơ-đun "lắp vào" hệ thống Chi tiết xảy bên mô-đun không cần xét đến hệ thống nói chung, miễn mơ-đun hồn thành tốt vai trị giao Đây gọi che giấu thơng tin (information hiding), nguyên lý quan trọng công nghệ phần mềm Một dạng thường thấy mơ-đun phần mềm chứa số liệu kèm theo số hàm/thủ tục để xử lý liệu Ví dụ, mơ-đun sổ địa chứa danh sách tên địa chỉ, kèm theo hàm/thủ tục để thêm mục tên mới, in nhãn địa chỉ…Với cách này, liệu bảo vệ xử lý theo cách biết trước định nghĩa chặt chẽ Ngồi ra, tạo thuận lợi cho chương trình sử dụng mơ-đun này, chương trình khơng phải quan tâm đến chi tiết biểu diễn liệu bên mô-đun Thông tin biểu diễn liệu che giấu Các mô-đun hỗ trợ dạng che giấu thông tin bắt đầu trở nên phổ biến ngơn ngữ lập trình đầu thập kỷ 1980 Từ đó, hình thức tiên tiến ý tưởng lan rộng ngành cơng nghệ phần mềm Cách tiếp cận gọi lập trình hướng đối tượng (object-oriented programming), thường gọi tắt OOP Câu chuyện tưởng tượng sau đây1 minh họa phần khác biệt lập trình thủ tục lập trình hướng đối tượng thực tế ngành cơng nghệ phàn mềm Có hai lập trình viên nhận đặc tả hệ thống yêu cầu xây dựng hệ thống đó, thi xem người hoàn thành sớm Dậu người chuyên dùng phương pháp lập trình thủ tục, cịn Tuất quen dùng lập trình hướng đối tượng Cả Dậu Tuất cho nhiệm vụ đơn giản Đặc tả sau: Nguồn: Head First Java, 2nd Edition Dậu tính tốn, "Chương trình phải làm gì? Ta cần đến thủ tục nào?" Anh tự trả lời, "xoay chơi nhạc." Và anh bắt tay vào viết thủ tục Chương trình khơng phải loạt thủ tục gì? Trong đó, Tuất nghĩ, "Trong chương trình có thứ đâu nhân tố chính?" Đầu tiên, nghĩ đến Hình vẽ Ngồi ra, anh cịn nghĩ đến đối tượng khác người dùng, âm thanh, kiện click chuột Nhưng anh có sẵn thư viện mã cho đối tượng đó, nên anh tập trung vào việc xây dựng Hình vẽ Dậu thạo với công việc kiểu rồi, anh bắt tay vào viết thủ tục quan trọng nhanh chóng hoàn thành hai thủ tục xoay (rotate) chơi nhạc (playSound): rotate(shapeNum) { // cho hình xoay 360o } playSound(shapeNum) { // dùng shapeNum để tra xem cần chơi file AIF // chơi file } Cịn Tuất ngồi viết ba lớp, lớp dành cho hình Dậu vừa nghĩ thắng sếp nói "Về mặt kĩ thuật Dậu xong trước, ta phải bổ sung chút xíu vào chương trình." Hai người quen với chuyện đặc tả thay đổi – chuyện thường ngày ngành Đặc tả bổ sung nội dung sau: Đối với Dậu, thủ tục rotate ổn, mã dùng bảng tra cứu để khớp giá trị shapeNum với hình đồ họa cụ thể Nhưng playSound phải sửa Rốt cục khơng phải sửa nghiêm trọng, Dậu thấy không thoải mái phải động vào sửa phần mã test xong từ trước Anh biết, dù quản lý dự án có nói nữa, đặc tả thay đổi suốt Cịn Tuất thản nhiên vừa nhâm nhi cà phê vừa viết lớp Điều anh thích OOP anh khơng phải sửa phần mã test bàn giao Anh nghĩ ích lợi OOP lẩm bẩm "Tính linh hoạt, khả mở rộng, " Dậu vừa kịp hoàn thành lát trước Tuất Nhưng nụ cười anh tắt nhìn thấy mặt sếp nghe thấy giọng sếp vẻ thất vọng "không rồi, amoeba thực không xoay kiểu " Thì hai lập trình viên viết đoạn xoay hình theo cách: (1) xác định hình chữ nhật bao hình; (2) xác định tâm hình chữ nhật xoay hình quanh điểm Nhưng hình trùng biến hình lại cần xoay quanh điểm đầu mút, kiểu kim đồng hồ "Mình tèo rồi." Dậu ngán ngẩm "Tuy là, ừm, thêm lệnh if/else vào thủ tục rotate, hard-code tâm xoay cho amoeba Làm không làm hỏng đoạn khác." Nhưng giọng nói đầu Dậu thào, "Nhầm to! Cậu có đặc tả khơng thay đổi lần không đấy?" Cuối Dậu chọn cách bổ sung tham số tâm xoay vào cho thủ tục rotate Rất nhiều đoạn mã bị ảnh hưởng Phải test lại, dịch lại đống mã Có đoạn trước chạy tốt khơng chạy rotate(shapeNum, xPt, yPt) { 10 phương thức add() để đưa đối tượng Dog vào danh sách Ta dùng mảng Dog đơn giản với kích thước để lưu đối tượng Dog đưa vào danh sách Khi danh sách đủ đối tượng, ta tiếp tục gọi phương thức add() khơng làm Nếu chưa đủ 5, phương thức add() gắn đối tượng vào vị trí cịn trống tăng số vị trí trống (nextIndex) thêm Nhưng ta cịn muốn quản lí mèo lẫn chó danh sách? Có vài lựa chọn Thứ nhất: viết thêm lớp MyCatList dành riêng cho đối tượng Cat Thứ hai: viết lớp DogAndCatList chung, có hai mảng, dành cho đối tượng Dog, dành cho đối tượng Cat Thứ ba: viết lớp AnimalList chấp nhận đối tượng thuộc lớp Animal (phịng trường hợp đặc tả lại thay đổi để yêu cầu nhận thêm loài vật khác) Lựa chọn thứ ba gọn gàng có khả mở rộng cao nên ta dùng cho phiên thứ hai Ta sửa lớp MyDogList, tổng quát hóa để chấp nhận lớp Animal thay Dog Lơ-gic chương trình giữ ngun cũ, có thay đổi đánh đậm đoạn mã đây: 128 public class AnimalList { private Animal[] animals = new Animal[5]; private int nextIndex = 0; AnimalList Animal[] animals int nextIndex public void add(Animal a) { add(Animal a) if (nextIndex < animals.length) { animals[nextIndex] = a; System.out.print("Animal added at " + nextIndex); nextIndex++; } } } public class AnimalTestDrive { public static void main(String [] args) { AnimalList list = new AnimalList(); d = new Dog(); c = new Cat(); list.add(d); % java AnimalTestDrive list.add(c); Animal added at } Animal added at } Hình 8.1: Ví dụ đa hình với lớp Animal Ta lại lấy ví dụ Shape nói đến đầu chương Lớp cha tổng quát Shape nên lớp trừu tượng ứng dụng không cần không nên tạo đối tượng Shape Ngoài ra, phương thức draw erase lớp nên phương thức trừu tượng ta khơng thể nghĩ nội dung hữu ích cho chúng Các lớp cụ thể, Point, Circle, Rectangle, lớp mà sau bổ sung vào thư viện cần, định nghĩa phiên với nội dung riêng cụ thể phù hợp với Chẳng hạn ví dụ Hình 8.2 Shape int x int y draw() erase() moveTo(x, y) Point draw() erase() Circle Rectangle double radius int height int width draw() erase() draw() erase() 129 abstract public class Shape { protected int x, y; protected Shape (int _x, int _y) { x = _x; y = _y; } abstract public void draw(); abstract public void erase(); public void moveTo(int _x, int _y) { erase(); x = _x; y = _y; draw(); } } public class Circle extends Shape { private double radius; public Circle(int _x, int _y, double _r) { super(_x, _y); radius = _r; } public void draw() { System.out.println("Draw circle"); } public void erase() { System.out.println("Erase circle"); } } Hình 8.2: Ví dụ đa hình với lớp Shape Khác với draw erase, moveTo lại phương thức định nghĩa lớp Shape Thuật toán ba bước cho moveTo cho hình: (1) xóa vị trí hành, (2) sửa tọa độ hình, (3) vẽ vị trí mới, xóa vẽ tùy theo loại hình cụ thể Hiệu ứng đa hình cho phép moveTo dùng đến phiên draw erase khác tùy theo gọi cho đối tượng thuộc loại hình Khi thư viện bổ sung thêm lớp đặc tả loại hình khác, ta phải cài draw erase cho loại hình mà khơng phải làm thêm cho phương thức biến đổi hình có quy trình chung định nghĩa sẵn tương tự moveTo Ví dụ minh họa mẫu thiết kế có tên Template Method (phương thức khn mẫu) Xem Hình 8.3 Ở đây, Shape lớp trừu tượng (AbstractClass) định nghĩa phương thức khuôn mẫu moveTo, quy định hai thao tác (PrimitiveOperation) erase draw mà phương thức khuôn mẫu dùng đến Circle lớp cụ thể (ConcreteClass), cài đặt thao tác Đây mẫu thiết kế thông dụng 130 Hình 8.3: Mẫu thiết kế Template Method 8.5 LỚP Object Thêm bước nữa, ta muốn có danh sách lưu đối tượng động vật sao? Ta tiếp tục thay đổi theo kiểu sửa kiểu mảng, kiểu đối số phương thức add() thành tổng qt trừu tượng Animal? Nhưng ta không viết lớp cha cho Animal Thực Animal có lớp cha Đối với Java, tất lớp lớp lớp Object Object tổ tiên tất Ngay từ đầu, ta viết lớp Object mà không biết, ta viết lớp Object mà không cần phải khai báo quan hệ thừa kế từ khóa extends Bất kì lớp khơng khai báo tường minh lớp lớp khác khai báo ẩn lớp Object Vậy nên, ta có Dog khơng phải lớp trực tiếp Object, Animal lớp trực tiếp Object, tất Dog, Cat, Canine, Animal nằm phả hệ có gốc Object Với tất lớp nằm thừa kế có Object gốc, chế đa hình cho phép ta tạo cấu trúc liệu dành cho đối tượng thuộc tất lớp Chẳng hạn mảng kiểu Object lưu đối tượng thuộc đủ loại Animal, Cow, Dog, Cat, PhoneBook, String Trong thư viện chuẩn Java có lớp ArrayList định nghĩa để quản lý đối tượng thuộc kiểu Object ArrayList dùng để quản lý đối tượng thuộc tất kiểu Lớp Object cho lớp khác thừa kế gì? Trong phương thức thừa kế Object có bốn phương thức thơng dụng: • boolean equals(Object o) kiểm tra xem hai đối tượng hành có 'bằng nhau' hay khơng, xem thêm ý nghĩa khái niệm 'bằng nhau' ti Ch-ơng 13 131 ã Class getClass() tr v lp mà đối tượng hành tạo từ đó, • int hashCode() trả mã băm đối tượng hành, ta tạm thời xem mã định danh đối tượng, • String toString() trả biểu diễn dạng String đối tượng, ta thường cài đè phương thức để trả biểu diễn String theo ý muốn ta thay trả chuỗi kí tự kết xuất cách tổng quát ví dụ bên 8.6 ĐỔI KIỂU – KHI ĐỐI TƯỢNG MẤT HÀNH VI CỦA MÌNH Rắc rối việc dùng chế đa hình coi thứ Object hay coi đối tượng động vật Animal đối tượng đánh (tạm thời) đặc trưng Dog đặc điểm chó Ta xem chuyện xảy phương thức trả tham chiếu tới đối tượng Dog khai báo kiểu trả Animal Nhớ lại lớp AnimalList ta tạo để quản lý danh sách vật Giả sử AnimalList có thêm phương thức get(int index) trả tham chiếu tới đối tượng đứng vị trí index danh sách Ta thử nghiệm chương trình DogTestDrive, đối tượng Dog tạo đưa vào danh sách AnimalList Sau ta gọi phương thức get() danh sách để lấy lại đối tượng vừa đưa vào 132 public class DogTestDrive { public static void main(String [] args) { AnimalList list = new AnimalList(); Dog d = new Dog(); list.add(d); lỗi biên dịch! d = list.get(0); } % javac DogTestDrive.java } DogTestDrive.java:6: incompatible types found : Animal required: Dog d = list.get(0); ^ error Để ý phương thức get() gọi từ list trả tham chiếu tới đối tượng Dog nói trên, dạng tham chiếu kiểu Animal Việc hồn tồn hợp lệ Nhưng trình biên dịch khơng biết thứ trả từ thực chất chiếu tới đối tượng Dog, khơng cho phép ta gán giá trị trả cho tham chiếu kiểu Dog Nếu ta gán giá trị cho tham số kiểu Animal, chẳng hạn, Animal a = list.get(0), trình biên dịch khơng phàn nàn Tuy nhiên, ta gọi phương thức mà Dog thừa kế từ Animal, chẳng hạn roam(), gọi phương thức mà Dog có, chaseCats() chẳng hạn Ngay ta biết chắn đối tượng có hành vi chaseCats (nó thực đối tượng Dog!), trình biên dịch nhìn thấy thứ kiểu Animal, mà Animal khơng có chaseCats() Vấn đề giống ta nói đến Mục 7.9 Để xác định xem ta gọi phương thức hay khơng, trình biên dịch dựa kiểu tham chiếu không dựa kiểu đối tượng thực tế Vậy chế thừa kế có chất nào? Mỗi đối tượng chứa tất thừa kế từ tất lớp cha, ơng, tổ tiên nó, có lớp Object Vậy nên coi thực thể lớp cha ơng Lấy ví dụ lớp Cow đơn giản Một đối tượng Cow đối xử khơng đối tượng Cow, cịn xem Object Khi ta gọi new Cow(), ta đối tượng heap – đối tượng Cow – 133 đối tượng có lõi phần Object (chữ O viết hoa) Một tham chiếu kiểu Cow tới đối tượng 'nhìn thấy' tồn đối tượng Cow, truy nhập tồn phương thức Cow, bao gồm phương thức thừa kế Trong đó, tham chiếu kiểu Object chiếu tới đối tượng 'nhìn thấy' phần Object đối tượng đó, truy cập phần Hình 8.4: Cấu trúc lớp phần thừa kế Như ta giải thích dùng tham chiếu kiểu lớp cha cho đối tượng thuộc lớp lớp sắc riêng Nhưng ta chưa giải xong vấn đề chương trình DogTestDrive Đối tượng mà ta lấy từ danh sách list thực Dog, làm cách để gọi phương thức Dog? Ta phải dùng tham chiếu khai báo kiểu Dog Sao chép tham chiếu kiểu Animal mà ta có ép sang kiểu Dog để ghi vào tham chiếu kiểu Dog Sau đó, ta dùng tham chiếu Dog để gọi phương thức Dog bình thường Nếu hành động ép kiểu ta sai, nghĩa đối tượng quan tâm thực kiểu Dog, chạy, chương trình ta bị ngắt chừng lỗi run-time ClassCastException Do đó, trường hợp mà ta không chắn kiểu đối tượng, ta dùng tốn tử instanceof để kiểm tra if (o instance of Dog) { Dog d = (Dog) o; 134 } 8.7 ĐA THỪA KẾ VÀ VẤN ĐỀ HÌNH THOI Cây thừa kế động vật vốn thiết kế để dùng cho toán giả lập môi trường sống động vật Nếu cần xây dựng phần mềm dạy học cho môn động vật học, ta tái sử dụng lớp thừa kế Giả sử ta nhận yêu cầu xây dựng phần mềm PetShop cho cửa hàng thú cảnh, ta muốn dùng lớp Dog cho phần mềm Hiện lớp động vật chưa có hành vi thú cảnh (Pet) play() beFriendly() Với vai trị lập trình viên cho lớp Dog, ta làm gì? Chỉ việc thêm phương thức cần thiết? Làm ta không phá vỡ mã khác ta khơng động đến phương thức có sẵn mà mã người khác gọi cho đối tượng Dog Đúng chưa đủ Lưu ý phần mềm cho cửa hàng thú cảnh, khơng có chó, ta khơng cần đến lớp Dog Việc bổ sung phương thức vào Dog, đó, có nhược điểm gì? Ta xét phương án: Phương án 1: đặt hành vi thú cảnh lớp Animal Ưu điểm: Tất lớp động vật có hành vi thú cảnh Ta sửa lớp khác, lớp tạo tương lai thừa kế Lớp Animal dùng làm kiểu đa hình chương trình muốn đối xử đồng loạt đối tượng Animal thú cảnh Nhược điểm: Hà mã, sư tử, chó sói chắn khơng phải thú cảnh nên Hippo, Lion, Wolf không nên có hành vi thú cảnh Kể cài đè hành vi thú cảnh lớp để chúng 'khơng làm gì' khơng ổn, hợp đồng lớp Hippo, Lion, cho đối tượng không thú cảnh có hành vi thú cảnh Đây cách tiếp cận tồi Ta không nên đưa vào lớp Animal thứ không áp dụng cho tất lớp Phương án 2: đặt hành vi thú cảnh lớp cần đến Ưu điểm: Khơng cịn rắc rối chuyện hà mã làm thú cảnh Dog Cat cài phương thức lớp khác khơng bị liên lụy Nhược điểm: Hai vấn đề nghiêm trọng: Thứ nhất, phải có giao thức chung mà từ trở tất lập trình viên cho lớp Animal phải biết Giao thức bao gồm phương thức mà ta định tất lớp thú cảnh phải có, tên gì, trả kiểu gì, đối số kiểu Nói cách khác hợp đồng thú cảnh Và ta khơng có cách để đảm bảo khơng có nhầm 135 Thứ hai, ta khơng có đa hình cho phương thức thú cảnh Khơng thể dùng tham chiếu Animal cho phương thức thú cảnh Tóm lại, ta cần gì? o Đặt hành vi thú cảnh lớp thú cảnh mà thơi o Đảm bảo tất lớp thú cảnh có viết phải có tất phương thức quy định (tên, đối số, kiểu trả ) mà ngồi hy vọng làm o Tận dụng lợi đa hình, cho gọi phương thức tất loại thú cảnh mà dùng riêng kiểu đối số, kiểu trả về, dùng mảng riêng cho loại Có vẻ ta cần đến HAI lớp cha thừa kế Khi lớp thừa kế từ nhiều lớp cha, ta có tình trạng gọi "đa thừa kế" Hình thức đa thừa kế có tiềm gây rắc rối nghiêm trọng gọi Vấn đề Hình thoi (the Diamond problem) ví dụ Hình 8.5 Trong ví dụ đó, hai lớp DVDBurner (thiết bị ghi đĩa DVD) CDBurner (thiết bị ghi đĩa CD) lớp DigitalRecorder (đầu thu kĩ thuật số), hai cài đè phương thức burn() thừa kế biến thành viên i Giả sử biến i dùng DVDBurner CDBurner, với giá trị khác Chuyện xảy ComboDrive – lớp thừa kế hai lớp – cần dùng đến hai giá trị i đó? Cịn nữa, gọi phương thức burn() cho đối tượng ComboDrive, phiên burn() chạy? 136 DigitalRecorder int i burn() DVDBurner CDBurner burn() burn() ComboDrive Hình 8.5: Ví dụ vấn đề Hình thoi đa thừa kế Ngơn ngữ lập trình cho phép đa thừa kế phải giải tình trạng rối rắm trên, phải có quy tắc đặc biệt để xử lý tình nhập nhằng ngữ nghĩa xảy C++ ngôn ngữ Java thiết kế theo tiêu chí đơn giản, nên khơng cho phép lớp thừa kế từ nhiều lớp cha Vậy ta phải giải toán thú cảnh với Java? 8.8 INTERFACE Giải pháp mà Java cung cấp interface Thuật ngữ interface tiếng Anh thường dùng với nghĩa 'giao diện', chẳng hạn "giao diện người dùng", hay câu "Các phương thức public lớp giao diện bên ngồi" Tuy nhiên, mục này, ta nói đến khái niệm interface với ý nghĩa cấu trúc lập trình Java định nghĩa với từ khóa interface (tương tự cấu trúc lớp định nghĩa với từ khóa class) Cấu trúc interface cho phép ta giải toán đa thừa kế, cho ta hưởng phần lớn ích lợi mang tính đa hình mà đa thừa kế mang lại, tránh cho ta rắc rối nhập nhằng ngữ nghĩa giới thiệu mục trước Nguy nhập nhằng ngữ nghĩa tránh cách đơn giản: phương thức phải trừu tượng! Theo đó, lớp buộc phải cài đặt phương thức Nhờ vậy, chương trình chạy, máy ảo Java khơng phải bối rối lựa chọn hai phiên mà đối tượng thừa kế Một interface, đó, giống lớp túy trừu tượng bao gồm toàn phương thức trừu tượng khơng có biến thực thể Nhưng cú pháp interface có khác lớp trừu tượng chút Để định nghĩa interface, ta dùng từ khóa interface thay class lớp: 137 public interface Pet { } Đối với lớp trừu tượng, ta cần tạo lớp cụ thể Còn interface, ta tạo lớp cài đặt phương thức trừu tượng mà interface quy định Lớp gọi lớp cài đặt interface mà ta nói đến Để khai báo lớp cài đặt interface, ta dùng từ khóa implements thay extends, theo sau tên interface Một lớp cài đặt vài interface đồng thời lớp lớp khác Chẳng hạn lớp Dog vừa lớp Canine, vừa lớp cài đặt interface Pet: class Dog extends Canine implements Pet { } Ví dụ cụ thể interface Pet lớp Dog cài đặt Pet cho Hình 1.1 Các phương thức interface ngầm định public abstract, ta khơng bắt buộc phải dùng hai từ khóa public abstract khai báo phương thức Do phương thức trừu tượng nên chúng khơng có thân mà có dấu chấm phảy cuối dịng khai báo Trong lớp Dog có hai loại phương thức: phương thức cài đặt interface Pet, phương thức cài đè lớp cha Canine thơng thường Hình 8.6: Lớp Dog cài đặt interface Pet Như ta dùng cấu trúc interface để thực thứ gần giống đa thừa kế Nó không đa thừa kế chỗ: khác với lớp trừu tượng, ta đặt mã cài đặt interface Khi phương thức interface trừu tượng, khơng thể tái sử dụng, ta ích lợi đây? Câu trả lời đa hình đa hình Khi ta dùng interface thay cho lớp riêng biệt làm tham số giá trị trả phương thức, ta truyền lớp cài đặt interface vào vị trí tham số hay giá trị trả Khơng có vậy, lớp nằm thừa kế khác cài đặt interface Trong thực tế, đa số thiết kế tốt, việc interface chứa mã cài đặt khơng phải vấn đề Lí hầu hết phương thức interface có đặc điểm 138 cài đặt cách tổng quát, đằng phải cài đè phương thức chúng không bị buộc phải phương thức trừu tượng Quay trở lại với ý lớp nằm thừa kế khác cài đặt interface Ta có ví dụ sau: Chó máy RoboDog loại robot loại thú cảnh Lớp RoboDog thuộc thừa kế Robot khơng thuộc Animal Tuy nhiên, cài interface Pet Cat Dog Khơng có vậy, lớp cịn cài đặt nhiều interface Sự linh hoạt interface đặc điểm vô quan trọng việc sử dụng Java API Ví dụ, để lớp đối tượng đâu thừa kế lưu file, ta cho lớp cài interface Serializable Khi nên cho lớp lớp độc lập, lớp con, lớp trừu tượng, hay nên biến thành interface? • Một lớp nên lớp độc lập, nghĩa khơng thừa kế lớp (ngoại trừ Object) khơng thỏa mãn kiểm tra IS-A loại khác • Một lớp nên lớp ta cần cho làm phiên chuyên biệt lớp khác cần cài đè hành vi có sẵn bổ sung hành vi • Một lớp nên lớp cha ta muốn định nghĩa khn mẫu cho nhóm lớp con, ta có chút mã cài đặt mà tất lớp sử dụng Cho lớp làm lớp trừu tượng ta muốn đảm bảo khơng tạo đối tượng thuộc lớp • Dùng interface ta muốn định nghĩa vai trị mà lớp khác nhận, lớp thuộc thừa kế Những điểm quan trọng: • Khi muốn cấm tạo đối tượng từ lớp, ta dùng từ khóa abstract định nghĩa lớp để tuyên bố lớp lớp trừu tượng • Một lớp trừu tượng có phương thức trừu tượng khơng trừu tượng • Nếu lớp có dù phương thức trừu tượng, lớp buộc phải lớp trừu tượng 139 • Một phương thức trừu tượng khơng có thân, khai báo phương thức kết thúc dấu chấm phảy • Một lớp cụ thể phải cài đặt thừa kế cài đặt tất phương thức trừu tượng • Mỗi lớp Java lớp trực tiếp gián tiếp lớp Object • Nếu ta dùng tham chiếu để gọi phương thức, tham chiếu khai báo thuộc lớp hay interface ta gọi phương thức có lớp interface đó, đối tượng mà tham chiếu chiếu tới đối tượng thuộc lớp • Một biến tham chiếu lớp cha gán giá trị tham chiếu kiểu lớp mà khơng cần đổi kiểu Có thể dùng phép đổi kiểu để gán giá trị tham chiếu kiểu lớp cha cho biến tham chiếu kiểu lớp con, nhiên chạy chương trình, phép đổi kiểu thất bại đối tượng chiếu tới khơng thuộc kiểu tương thích với phép đổi kiểu • Java khơng hỗ trợ đa thừa kế vấn đề Hình thoi Java cho phép lớp có lớp cha • Một interface tương tự với lớp túy trừu tượng Nó định nghĩa phương thức trừu tượng • Một lớp cài đặt nhiều interface • Lớp cài đặt interface phải cài tất phương thức interface đó, tất phương thức interface phương thức trừu tượng public Đọc thêm Bạn đọc tìm hiểu sâu mẫu thiết kế tài liệu sau: Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1994 140 Bài tập Điền từ thích hợp vào chỗ trống a) Nếu lớp chứa phương thức trừu tượng phải lớp b) Các lớp mà từ tạo đối tượng gọi lớp _ c) _ cho phép sử dụng tham chiếu kiểu lớp cha để gọi phương thức từ đối tượng lớp cha lớp con, cho phép ta lập trình cho trường hợp tổng quát d) Các phương thức phương thức interface không cung cấp cài đặt phương thức phải khai báo với từ khóa _ Các phát biểu sau hay sai: a) Nếu lớp cha khai báo phương thức trừu tượng lớp buộc phải cài phương thức b) Một đối tượng thuộc lớp cài đặt interface coi đối tượng thuộc kiểu interface Phương thức trừu tượng gì? Hãy mơ tả tình mà ta nên khai báo phương thức phương thức trừu tượng So sánh lớp trừu tượng interface, ta nên dùng lớp trừu tượng, nên dùng interface? Đa hình hỗ trợ cho khả mở rộng thừa kế? Liệt kê kiểu gán tham chiếu lớp cha lớp cho biến kiểu lớp cha lớp con, kiểu có thơng tin quan trọng gì? Giải thích quan điểm đa hình cho phép lập trình tổng quát thay lập trình cho trường hợp cụ thể Dùng ví dụ minh họa Lập trình tổng qt mang lại ích lợi gì? Một lớp thừa kế giao diện hay cài đặt từ lớp cha Một thừa kế thiết kế thừa kế giao diện khác với thừa kế dành cho thừa kế cài đặt nào? Cài đặt 03 lớp 02 interface sơ đồ sau Trong lớp Numeral (số) Square (bình phương) cài đặt interface Expression (biểu thức, lớp Addition (phép cộng) cài đặt interface BinaryExpression (nhị thức – biểu thức có hai tốn hạng), interface lại thừa kế Expression 141 Expression +toString:String + evaluate() BinaryExpression Numeral + left(): Expression +right() : Expression int: value Square Expression: expression 142 Addition Expression: left Expression: right ... LỆ LÀ GÌ? 17 5 11 .1. 1 Tình cố 17 5 11 .1. 2 Xử lý ngoại lệ 17 7 11 .1. 3 Ngoại lệ đối tượng 17 8 11 .2 KHỐI try/catch 17 9 11 .2 .1 Bắt nhiều ngoại lệ 17 9 11 .2.2 Hoạt động... 18 9 11 .6 ĐỊNH NGHĨA KIỂU NGOẠI LỆ MỚI 19 0 11 .7 NGOẠI LỆ VÀ CÁC PHƯƠNG THỨC CÀI ĐÈ 19 1 Chương 12 CHUỖI HÓA ĐỐI TƯỢNG VÀ VÀO RA FILE 19 6 12 .1 QUY TRÌNH GHI ĐỐI TƯỢNG 19 7 12 .2 CHUỖI HÓA ĐỐI... KẾ? 11 0 7.6 LỢI ÍCH CỦA QUAN HỆ THỪA KẾ 11 0 7.7 ĐA HÌNH 11 1 7.8 GỌI PHIÊN BẢN PHƯƠNG THỨC CỦA LỚP CHA 114 7.9 CÁC QUY TẮC CHO VIỆC CÀI ĐÈ 11 5 7 .10 CHỒNG PHƯƠNG THỨC 11 6 7 .11 CÁC

Ngày đăng: 09/05/2021, 16:22