Vì vậy bài đầu tiên này mình muốn dành để nói về lập trình hướng đối tượng là gì, và quan điểm của giới lập trình về nó như thế nào, tại sao nó lại là một mô hình tiên tiến và bạn sẽ khô
BÀI SƠ LƯỢC VỀ LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG – OBJECT ORIENTED PROGRAMMING ム 少 _ Tất ngơn ngữ lập trình sinh để hỗ trợ phong cách lập trình hay mơ hình lập trình (programming paradigm) Vì trước bắt tay vào học ngơn ngữ ta nên tìm hiểu sơ lược mơ hình lập trình ngơn ngữ hỗ trợ mà ta dự định viết chương trình theo mơ hình Cụ thể, nói “lập trình hướng đối tượng với C++” ta phải biết sơ sơ hướng đối tượng trước “ngâm cứu” C++ Vì muốn dành để nói lập trình hướng đối tượng gì, quan điểm giới lập trình nào, lại mơ hình tiên tiến bạn khơng phải hối hận bỏ thời gian công sức để học Ngày xửa ngày xưa, khoảng ba chục năm trước, quy mô dự án phần mềm cịn nhỏ, lập trình viên gần viết chương trình mà khơng cần suy nghĩ nhiều (giả sử khơng có lập trình viên bị thiểu trí tuệ Thời lập trình cấu trúc (structured programming) hay cịn gọi lập trình thủ tục (procedural programing) kỹ thuật lập trình chủ yếu Tớ nói sơ qua chút kỹ thuật (trong phạm vi hiểu biết) Theo quan điểm lập trình cấu trúc, người ta xem chương trình “công việc lớn” cần phải xử lý Để giải “cơng việc lớn” này, người ta tìm cách chia thành phần công việc nhỏ phần quẳng cho hàm đảm nhiệm Chương trình gọi đến hàm vào thời điểm cần thiết Trong hàm, phần cơng việc cịn lớn, ta lại chia nhỏ tiếp vấn đề trở nên đủ đơn giản Và dĩ nhiên để giải phần ta phải quẳng chúng cho hàm tương ứng Quá trình gọi “làm mịn” hay “tinh chế bước” (stepwise refinement) Việc trao đổi liệu hàm thực thông qua việc truyền đối số biến, mảng toàn cục Như coi chương trình tập hợp hàm thiết kế để xử lý phần cơng việc giao Các ngơn ngữ lập trình hướng thủ tục thường gặp C, Pascal, FORTRAN … C++ Tuy nhiên C++ thiết kế để hỗ trợ lập trình hướng đối tượng Một chương trình viết theo hướng cấu trúc tập trung vào trình xử lý Nghĩa câu lệnh dẫn cho máy tính làm việc đó, kiểu như: nhận số nguyên từ bàn phím, cộng chúng lại với nhau, đem chia đôi, hiển thị kết lên hình Một chương trình tập dẫn Lập trình cấu trúc tỏ hiệu quy mơ chương trình cịn nhỏ, quy mơ chương trình lớn dần lên phức tạp bộc lộ nhiều khiếm khuyết Có thể nêu số vấn đề sau: Trọng tâm vào “hành động” “dữ liệu”: thực tế liệu tối thượng mà quan tâm Mọi chương trình nhằm mục đích nhét liệu vào input chờ đợi kết output Rõ ràng mục đích ta liệu đầu ra, mặc kệ chương trình muốn xử lý xử lý, ta quan tâm đến kết đầu có đạt u cầu hay khơng Tuy nhiên lập trình cấu trúc trọng đến việc thiết kế hàm (hành động) mà xem nhẹ liệu, hạn chế thứ Tính bảo mật liệu không cao: (nếu không muốn nói khơng có) Dữ liệu chương trình gần chung, dễ dàng truy cập hay sửa đổi cách vô tội vạ Những hàm khơng phận tọc mạch vào vùng liệu mà “chằng liên quan” sửa đổi Điều làm chương trình dễ phát sinh lỗi đặc biệt “lỗi tinh vi” “lỗi logic” Và có lỗi khó debug phạm vi khoanh vùng rộng (vì tọc mạch vào liệu nên nghi cho thằng nào) Đây hạn chế thứ hai Hướng dẫn lập trình hướng đối tượng với C++_ first_pace Tách rời liệu với “hành động” liên quan: tất hàm viết để dùng cho tất liệu, ngược lại Mỗi nhóm liệu sử dụng nhóm hàm “dành riêng cho chúng” Trong lập trình, việc “đóng gói” liệu hàm liên quan gọi “mơ-đun hóa” (modularization) Điều có hai lợi Thứ nhất, hàm liệu nhóm lại với nên “gọn gàng” dễ kiểm sốt Thứ hai, thơng thường hàm khối truy nhập vào liệu khối Do hạn chế tọc mạch từ bên ngồi, tính bảo mật liệu cao hơn, hạn chế lỗi phạm vi khoanh vùng lỗi thu hẹp Tuy nhiên, lập trình cấu trúc khơng làm điều Đây hạn chế thứ ba Phụ thuộc nặng nề vào cấu trúc liệu thuật tốn: minh chứng cho điều câu nói tiếng bác Niklaus Wirth (creator of Pascal): Algorithms + Data Structures = Programs Cũng xin nói thêm mơ hình lập trình hướng cấu trúc dựa mơ hình tốn học Bohm Guiseppe (nói thật khơng biết hai bác này, theo đó, chương trình máy tính viết dựa ba cấu trúc là: (sequence), lựa chọn hay rẽ nhánh (selection) lặp (repetition) Vì chương trình xem chuỗi hành động liên tiếp để đến kết cuối Và việc thiết kế chương trình phụ thuộc nặng nề vào việc dùng giải thuật tổ chức liệu Điều làm cho việc thiết kế “khơng tự nhiên” làm cho q trình thiết kế phụ thuộc vào cài đặt quy mô chương trình lớn dần lên khó triển khai Đồng thời có thay đổi cấu trúc liệu nâng cấp chương trình gần ta phải viết lại hầu hết hàm liên quan sửa đổi lại thuật tốn cấu trúc liệu phù hợp với số thuật toán định Đây hạn chế thứ tư Không tận dụng mã nguồn: hàm phát minh quan trọng để tăng cường khả sử dụng lại mã nguồn, nhiên lập trình cấu trúc điều không triệt để Ta phải viết lại đoạn code hao hao giống để thực cơng việc tương tự Ví dụ: C, hàm hàm int min(int x, int y) có nhiệm vụ tính toán trả hai số nguyên truyền vào, hàm float min(float x, float y) làm nhiệm vụ tương tự với số thực Rõ ràng nội dung hai hàm giống đến 99%, có khác khác kiểu int float, C ta phải viết hai hàm khác Trong C++, với định hướng đối tượng ta viết hàm dùng để dùng cho kiểu int, float, double Ngồi cịn nhiều điểm mạnh khác mà OOP mang lại để tận dụng tối đa khả sử dụng lại mã nguồn tính kế thừa (inheritance), đa hình (polymorphism) Đây hạn chế thứ năm lập trình cấu trúc Nói chung bới thơi, biết thêm bổ sung Rõ ràng với nhiều hạn chế lập trình cấu trúc giải phải pháp tốt Và nỗ lực để vá lỗ hổng dẫn đến đời kỹ thuật lập trình lập trình hướng đối tượng (object oriented programming – OOP) Mình nói sơ qua chút OOP Khác với lập trình cấu trúc, OOP coi chương trình tập hợp đối tượng có quan hệ với Mỗi đối tượng có liệu phương thức riêng Ví dụ đối tượng Human có liệu như: tên, ngày sinh, tuổi, số chứng minh nhân dân, nghề nghiệp, … blah blah … đóng gói phương thức kèm ví dụ phương thức set_name() cho phép nhập tên , get_name() cho phép lấy tên đối tượng, tương tự ta cho phương thức set_ID(), get_ID() cho chứng minh nhân dân … Các đối tượng sử dụng phương thức để giao tiếp với bên Việc trước Hướng dẫn lập trình hướng đối tượng với C++_ first_pace giúp liệu quan tâm mức, an toàn Mọi truy cập đến liệu kiểm soát thông qua phương thức cung cấp sẵn nên hạn chế truy cập bất hợp pháp Tức giải ba hạn chế lập trình cấu trúc Thứ hai, thay đổi liệu ảnh hưởng đến số lượng hàm định thay phải viết lại hầu hết hàm ta phải viết lại số hàm có liên quan trực tiếp đến thay đổi Ví dụ thành phần liệu name biểu thị tên đối tượng Human lý đổi thành full_name hàm liên quan trực tiếp đến name set_name() hay get_name() phải viết lại, hàm set_ID(), get_ID() hay chí hàm gọi hàm set_name() get_name() chẳng việc Điều thuận lợi cho việc nâng cấp bảo trì Tức hạn chế thứ tư giải OOP cung cấp khái niệm kế thừa đa hình giúp tận dụng tối đa khả sử dụng lại mã nguồn để giảm bớt vất vả cho lập trình viên tăng chất lượng phần mềm Ví dụ tạo lớp (class) Girl, kế thừa từ lớp Human Khi đó, đối tượng thuộc lớp Girl có đầy đủ thuộc tính phương thức Human, ta cần bổ sung thêm phần khác số đo ba vịng: round_1, round_2, round_3 … Vì thể khơng phải viết lại toàn code cho lớp Girl Cụ thể đề cập post sau Đây mở đầu để giúp người so sánh kỹ thuật OOP với kỹ thuật lập trình cấu trúc truyền thống có hình dung OOP, ưu điểm mà mang lại, lại kỹ thuật ưa chuộng Trong năm gần đây, lập trình dịch chuyển từ hướng cấu trúc sang hướng đối tượng ưu điểm khả mạnh mẽ Thực tế OOP sử dụng rộng rãi dự án phần mềm, cịn lập trình cấu trúc chiếm phần nhỏ thường giải vấn đề có quy mơ nhỏ dùng giảng dạy để giúp người học bước đầu làm quen với lập trình Đấy nghe thiên hạ nói thơi học OOP nên thực tế doanh nghiệp viết phần mềm ngơn ngữ Nhưng có điều cảm nhận OOP lập trình sướng hơn lập trình cấu trúc nhiều, khoản thiết kế trực quan hơn, rõ ràng hơn, thật Còn để ý kỹ cài đặt chi tiết hướng đối tượng suy cho lập trình cấu trúc, có điều chúng tổ chức tốt phủ lên giao diện mang tính hướng đối tượng mà BÀI NHỮNG ĐẶC TRƯNG CƠ BẢN CỦA OOP Chúng ta xem xét sơ qua số khái niệm thành phần OOP nói chung C++ nói riêng Đối tượng (Objects) Khi thiết kế chương trình theo tư hướng đối tượng người ta không hỏi “vấn đề chia thành hàm nào” mà “vấn đề giải cách chia thành đối tượng nào” Tư theo hướng đối tượng làm cho việc thiết kế “tự nhiên” trực quan Điều xuất phát từ việc lập trình viên cố gắng tạo phong cách lập trình giống đời thực tốt Nếu ngồi đời có cơng nơng Hướng dẫn lập trình hướng đối tượng với C++_ first_pace thiết kế ta bê ngun cơng nơng vào chương trình, chương trình tập hợp tất đối tượng có liên quan với Tất thứ trở thành đối tượng OOP, có giới hạn trí tưởng bạn Đối tượng thực thể tồn chương trình chạy Nó có thuộc tính (attributes) phương trức (methods) riêng Lớp (Classes) Trong đối tượng thực thể xác định lớp lại khái nhiệm trừu tượng Có thể so sánh lớp “kiểu liệu cịn” đối tượng “biến” có kiểu lớp Ví dụ: lớp Cơng_nơng mơ tả sau: Lớp Cơng_nơng Thuộc tính: Nhãn hiệu (ví dụ Lamborghini) Màu xe Giá xe Vận tốc tối đa (ví dụ 300 km/h) Phương thức: Khởi động Chạy thẳng Rẽ trái / phải Dừng Tắt máy Một khai báo: C++ Code: Công_nông cơng_nơng_của_tơi; Hồn tồn tương tự khai báo: C++ Code: int my_integer; Tạo lớp tương tự tạo kiểu liệu – kiểu người dùng tự định nghĩa (user-defined type) Lớp “khuôn” để đúc đối tượng.Một đối tượng thuộc lớp Công_nông có đầy đủ thuộc tính phương thức mô tả trên, trường hợp cơng_nơng_của_tơi đúc từ “khn” Cơng_nơng Có tương ứng lớp đối tượng chất lại khác Lớp trừu tượng hóa đối tượng, đối tượng thể (instance) lớp Đối tượng thực thể có thực, tồn hệ thống, cịn lớp khái niệm trừu tượng tồn dạng khái niệm để mơ tả đặc tính chung cho đối tượng Tất đối tượng lớp có thuộc tính phương thức giống Sự đóng gói trừu tượng hóa liệu (Encapsulation & Data Abstraction) Nhìn lại thí dụ đối tượng thuộc lớp Cơng_nơng có thuộc tính phương thức “đóng gói” chung lại Muốn truy cập vào thành phần liệu bắt buộc phải thông qua phương thức, phương thức tạo giao diện để đối tượng Hướng dẫn lập trình hướng đối tượng với C++_ first_pace giao tiếp với bên Giao diện giúp cho liệu bảo vệ ngăn chặn truy cập bất hợp pháp, đồng thời tạo thân thiện cho người dùng Ví dụ: C, xâu lưu trữ mảng str đó, muốn biết độ dài xâu ta phải gọi hàm strlen() thư viện C++, str đối tượng thuộc lớp string tự “biết” kích thước mình, cần gọi str.size() str.length() trả độ dài xâustr Người dùng hồn tồn khơng cần biết cài đặt chi tiết bên lớp string mà cần biết “giao diện” để giao tiếp với đối tượng thuộc lớp string ok Điều dẫn đến trừu tượng hóa liệu Nghĩa bỏ qua cài đặt chi tiết quan tâm vào đặc tả liệu phương thức thao tác liệu Đặc tả lớp Công_nông trừu tượng hóa liệu Sự kế thừa (Inheritance) Những ý tưởng lớp dẫn đến ý tưởng kế thừa Trong sống hàng ngày thấy nhiều ví dụ kế thừa (tất nhiên thừa kế vê tài sản Ví dụ:lớp động vật phân chia thành nhiều lớp nhỏ lớp côn trùng, lớp chim, lớp động vật có vú, khơng có vú … blah blah … hay lớp phương tiện chia thành lớp nhỏ xe đạp, xe thồ, xe tăng, xích lơ, … Các lớp nhỏ gọi lớp (subclass) hay lớp dẫn xuất (derived class) cịn lớp phía gọi lớp cha (super class) hay lớp sở (base class) Một nguyên tắc chung lớp có đặc điểm chung thừa hưởng từ lớp cha mà kế thừa Ví dụ lớp trùng động vật có vú có đặc điểm chung lớp động vật Và ta cần bổ sung đặc điểu cần thiết thay viết lại tịan code Điều giảm gánh nặng cho lập trình viên góp phần giảm chi phí sản xuất bảo trì, nâng cấp phần mềm Tính đa hình tải (Polymorphism & Overloading) Giả sử ta xây dựng lớp String để “đúc” đối tượng lưu trữ xâu ký tự, ví dụ ta có đối tượng s1, s2, s3 thuộc lớp String Ta muốn thiết kế lớp String cho câu lệnh C++ Code: s3 = s1 + s2 ; thực việc nối xâu s2 vào đuôi xâu s1 gán kết cho xâu s3 Nếu công việc lập trình trơng “tự nhiên” Nhưng thật khơng may ngơn ngữ lập trình khơng cung cấp sẵn điều Sử dụng toán tử (operators) + = gây lỗi Tuy nhiên C++ cung cấp chế cho phép lập trình viên “định nghĩa lại” tốn tử để dùng mục đích khác Việc định nghĩa lại cách sử dụng toán tử gọi “quá tải toán tử” (operator overloading) Một số người gọi “nạp chồng tốn tử” thích dùng từ q tải nghe “cơ khí” C++ cho phép q tải hầu hết tốn tử thơng dụng +, -, *, /, [], , … Ngoài việc cho phép q tải tốn tử, C++ cịn cho phép “q tải hàm” (function overloading), nói kỹ khác Nói chung overloading cách cho phép ta sử dụng toán tử hàm cách khác tùy theo ngữ cảnh, trường hợp “tính đa hình” (polymorphism), tính quan trọng OOP Hướng dẫn lập trình hướng đối tượng với C++_ first_pace BÀI MỘT CHƯƠNG TRÌNH C++ ĐƠN GIẢN Bây xem xét chương trình C++ đơn giản sau C++ Code: // my first program in C++ #include using namespace std; int main(){ cout