Anaconda Distribution là trình quản lý gói, quản lý môi trường và phân phối Python miễn phí, dễ cài đặt với bộ sưu tập hơn 1000 gói nguồn mở với sự hỗ trợ cộng đồng miễn phí.
Anaconda là độc lập nền tảng, vì vậy chúng ta có thể sử dụng trên Windows, macOS hay Linux.
Trong bài này chúng ta thực hiện nội dung thứ hai là cài đặt Anaconda cho Python 3.7 trên CentOS 7.
Các bước cài đặt Anaconda cho Python 3.7
Bước 1.
Chúng ta thực hiện download Anaconda cho Python 3.7 trên Linux tại website:
Xác định chỉ số i của phần tử x[i] đứng liền trước đoạn cuối đó.
Nếu tìm thấy chỉ số i như trên: (i) tìm phần tử x[k] nhỏ nhất thoả mãn điều kiện x[k] > x[i]; (ii) Đảo giá trị x[k] và x[i]; (iii) Lật ngược thứ tự đoạn cuối giảm dần (từ x[i+1] đến x[k]) trở thành tăng dần.
Nếu không tìm thấy tức là toàn dãy đã sắp giảm dần, đây là cấu hình cuối cùng.
Bước 1.
Chúng ta định nghĩa một mảng gồm n phần tử.
Bước 2.
Chúng ta gán giá trị là chỉ số vị trí tương ứng cho từng phần tử trong mảng.
Bước 3.
Chúng ta thực hiện thuật toán sinh trong vòng lặp while() {}.
Nội dung chính của thuật toán bao gồm các bước từ 3.1 đến 3.4.
Bước 3.1.
Tại từng bước lặp, chúng ta nhận được một hoán vị.
Chúng ta thêm hoán vị này vào danh sách sequences.
Bước 3.2.
Chúng ta duyệt các phần tử từ cuối dãy trở lại.
Bước 3.3.
Chúng ta thực hiện xem xét nếu chưa gặp phải hoán vị cuối.
Việc kiểm tra được thực hiện từ Bước 3.3.1 đến 3.3.3.
Bước 3.3.1.
Chúng ta duyệt các phần tử từ cuối dãy trở lại.
Bước 3.3.2.
Chúng ta lùi dần k.
Bước 3.3.3.
Chúng ta thực hiện đổi chỗ x[k] và x[i].
Bước 3.3.4.
Chúng ta điều chỉnh những phần tử sau x[i].
Bước 3.4.
Thuật toán sinh dừng lại khi toàn bộ dãy giảm dần.
Thử nghiệm
Chúng ta thử nghiệm phương thức generatePermutation() trong class Main.py.
Kết luận
Trong nội dung bài này, chúng ta đã cùng tìm hiểu một số bài toán con đối với thuật toán sinh để liệt kê một danh sách theo yêu cầu cho trước.
Hi vọng chúng ta có thể hiểu thêm về tư duy thuật toán cũng như một số các kỹ thuật lập trình Python để áp dụng cho các bài khác.
Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.
Những nội dung chính sẽ được trình bày trong nhóm bài:
Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.
Nội dung chính của bài này là trình bày phần thứ hai và tập trung vào Tầng 2 trong nội dung về kỹ thuật lập trình với ngôn ngữ Python:
Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.
Class BaseService
Bước 1.
Chúng ta thiết kế lớp cơ sở BaseService như sau:
Bước 2.
Chúng ta đặc tả các phương thức chính trong class BaseService:
Class CategoryService
Chúng ta thiết kế lớp dẫn xuất CategoryService như sau:
Class ProductService
Chúng ta thiết kế lớp dẫn xuất ProductService như sau:
Kết luận
Trong bài này, chúng ta cùng nhau tìm hiểu việc thực hiện kỹ thuật lập trình cho phần thứ hai và tập trung vào Tầng 2.
Chúng ta có thể áp dụng những kiến thức trong nhóm bài để thực hiện một số bài tập:
Thêm / xóa / sửa / truy vấn dữ liệu trong bảng category và product theo những yêu cầu thực tế khác nhau.
Thay đổi cơ sở dữ liệu PostgreSQL bởi các cơ sở dữ liệu khác: MySQL / MariaDB; Oracle; …
Nhóm bài này sẽ trở thành một trong những kiến thức nền để thực hiện các dạng phần mềm: Desktop / Web Application.
Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.
Những nội dung chính sẽ được trình bày trong nhóm bài:
Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.
Nội dung chính của bài này là trình bày phần thứ hai và tập trung vào Tầng 3 trong nội dung về kỹ thuật lập trình với ngôn ngữ Python:
Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.
Class BaseDAO – Kiến trúc tổng quan
Bước 1.
Chúng ta thiết kế lớp cơ sở BaseDAO thành abstract class như sau:
Bước 2.
Chúng ta định nghĩa các phương thức chính trong class BaseDAO:
Class BaseDAO – Phương thức getConnection()
Chúng ta đặc tả phương thức getConnection() đối với tác vụ kết nối đến PostgreSQL:
Class BaseDAO – Phương thức selectDataFromOneTable()
Bước 1.
Chúng ta đặc tả phương thức selectDataFromOneTable() đối với tác vụ truy xuất dữ liệu từ một bảng trong PostgreSQL.
Mã nguồn SQL tổng quan để thực hiện truy vấn dữ liệu:
SELECT column_i, …, column_j FROM table [WHERE column_k = value_k AND … AND column_l = value_l]
Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:
Bước 2.
Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:
Kỹ thuật lập trình cần chú ý ở đây:
Giá trị của từng trường điều kiện được thể hiện bằng dấu “%s”.
Chúng ta sẽ thay thế từng dấu “%s” bằng giá trị tương ứng trong dataSet ở các bước sau.
Đây là bước đầu tiên của kỹ thuật Prepared Statement. Kỹ thuật này giúp truy xuất dữ liệu thuận tiện hơn, độc lập cơ sở dữ liệu và phần nào chống được kỹ thuật tấn công SQL Injection.
Bước 3.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 4.
Chúng ta định nghĩa một cursor:
Đây là bước thứ hai của kỹ thuật Prepared Statement giúp chuẩn bị thay thế từng dấu “%s” trong chuỗi SQL bởi giá trị tương ứng.
Bước 5.
Chúng ta thực hiện truy vấn dữ liệu.
Chúng ta tiếp tục gọi phương thức mappingData() để thực hiện việc chuyển đổi dữ liệu trong thực thể này về dạng mong muốn và thêm vào results.
Kỹ thuật lập trình cần chú ý ở đây:
Chúng ta định nghĩa phương thức mappingData() là abstract trong class BaseDAO.
Chúng ta đặc tả cụ thể các kỹ thuật lập trình của phương thức mappingData() trong các lớp dẫn xuất là CategoryDAO và ProductDAO.
Bước 6.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class BaseDAO – Phương thức insertData()
Bước 1.
Chúng ta đặc tả phương thức insertData() đối với tác vụ thêm dữ liệu vào một bảng trong PostgreSQL.
Mã nguồn SQL tổng quan để thực hiện thêm dữ liệu:
INSERT INTO table (column_i, …, column_j) VALUE (value_i, …, value_j)
Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:
Bước 2.
Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:
Bước 3.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 4.
Chúng ta định nghĩa một thực thể cursor:
Bước 5.
Chúng ta thực hiện thêm dữ liệu:
Bước 6.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class BaseDAO – Phương thức updateData()
Bước 1.
Chúng ta đặc tả phương thức updateData() đối với tác vụ cập nhật dữ liệu trong một bảng trong PostgreSQL.
Mã nguồn SQL tổng quan để thực hiện thêm dữ liệu:
UPDATE table SET (column_i = value_i, …, column_j = value_j) [WHERE column_k = value_k AND … AND column_l = value_l]
Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:
Bước 2.
Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:
Bước 3.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 4.
Chúng ta định nghĩa một thực thể cursor:
Bước 5.
Chúng ta thực hiện cập nhật dữ liệu:
Bước 6.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class BaseDAO – Phương thức deleteData()
Bước 1.
Chúng ta đặc tả phương thức deleteData() đối với tác vụ xóa dữ liệu trong một bảng trong PostgreSQL.
Mã nguồn SQL tổng quan để thực hiện truy vấn dữ liệu:
DELETE FROM table WHERE column_k = value_k AND … AND column_l = value_l
Chúng ta đặc tả chuỗi SQL như sau:
Bước 2.
Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:
Bước 3.
Chúng ta định nghĩa một thực thể cursor:
Bước 4.
Chúng ta thực hiện xóa dữ liệu:
Bước 5.
Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:
Class CategoryDAO
Chúng ta thiết kế lớp dẫn xuất CategoryDAO như sau:
Class ProductDAO
Chúng ta thiết kế lớp dẫn xuất ProductDAO như sau:
Kết luận
Trong bài này, chúng ta cùng nhau tìm hiểu việc thực hiện kỹ thuật lập trình cho phần thứ hai và tập trung vào Tầng 3.
Trong bài tiếp theo, chúng ta cùng tìm hiểu việc thực hiện kỹ thuật lập trình cho Tầng 2.
Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.
Những nội dung chính sẽ được trình bày trong nhóm bài:
Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.
Nội dung chính của bài này là trình bày phần thứ nhất trong nội dung về kỹ thuật lập trình với ngôn ngữ Python:
Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.
Xây dựng kiến trúc tổng quan của mô hình 3 lớp
Bước 1.
Chúng ta tạo mới PyDev Project trong Eclipse IDE và đặt tên là PythonThreeTiersProject.
Chúng ta tạo class Main trong package main.
Chúng ta sẽ thực hiện các kỹ thuật lập trình về đặc tả giao diện Console ở Tầng 1.
Bước 2.
Chúng ta tạo class BaseService trong package service.
Đây là lớp cơ sở của Tầng 2 về xử lý các tác vụ trung gian.
Bước 3.
Chúng ta tạo class CategoryService và ProductService trong package service.
Đây là các lớp dẫn xuất của BaseService để thực thi cụ thể các tác vụ ở Tầng 2.
Bước 4.
Chúng ta tạo class BaseDAO trong package dao.
Đây là lớp cơ sở của Tầng 3 về xử lý các tác vụ kết nối và truy vấn cơ sở dữ liệu.
Bước 5.
Chúng ta tạo class CategoryDAO và ProductDAO trong package dao.
Đây là các lớp dẫn xuất của BaseDAO để thực thi cụ thể các tác vụ ở Tầng 3.
Thiết lập driver điều khiển để kết nối PostgreSQL
Chúng ta cài đặt thư viện psycopg2 trong Anaconda.
Kết luận
Trong bài này, chúng ta đã cùng nhau tìm hiểu việc xây dựng kiến trúc tổng quan của mô hình 3 lớp cho một PyDev Project.
Trong bài tiếp theo, chúng ta sẽ cùng thực hiện các tác vụ cụ thể.
Trong nội dung bài này, chúng ta cùng nhau tìm hiểu kỹ thuật cơ bản trong Python để kết nối và truy vấn Cơ sở dữ liệu MySQL.
Những nội dung chính được trình bày trong bài này:
Thiết kế một bảng cơ sở dữ liệu đơn giản gồm một số các trường cơ bản.
Cấu hình Hệ quản trị phpMyAdmin để thực hiện việc kết nối và truy xuất được thuận tiện.
Kỹ thuật cơ bản trong Python bao gồm việc thêm mới dữ liệu và truy xuất toàn bộ dữ liệu trong bảng.
Thiết kế Cơ sở dữ liệu đơn giản
Chúng ta thiết kế bảng users gồm các trường như sau:
Mã nguồn SQL để thực hiện tạo bảng users trong MySQL:
Chúng ta lưu thành file Create_MySQL.sql.
Cấu hình Hệ quản trị phpMyAdmin
Bước 1.
Chúng ta khởi động LAMP Stack Control Panel.
Chúng ta start service MySQL Database và Apache Web Server.
Bước 2.
Chúng ta mở giao diện phpMyAdmin trên trình duyệt với địa chỉ:
127.0.0.1:8080/phpmyadmin/
Chúng ta nhập username và password để đăng nhập vào phpMyAdmin.
Ví dụ ở đây là:
Username : root
Password : adminadmin
Bước 3.
Giao diện màn hình chính của phpMyAdmin hiện ra.
Chúng ta nhận thấy địa chỉ chính thức của MySQL: localhost:3306.
Bước 4.
Chúng ta mở tab Databases trong phpMyAdmin.
Chúng ta nhập thông tin tạo database mới trong mục Create database:
firstdb
utf8_unicode_ci
Chúng ta lựa chọn nút Create để tạo database firstdb.
Bước 5.
Giao diện của database firstdb hiện ra.
Bước 6.
Chúng ta mở tab Import trong giao diện của firstdb.
Chúng ta lựa chọn file Create_MySQL.sql đã được tạo ra bên trên.
Chúng ta lựa chọn nút Go để thực hiện Import.
Bước 7.
Giao diện firstdb sau khi đã thực hiện import và tạo mới bảng users:
Bước 8.
Chúng ta lựa chọn bảng users.
Chúng ta lựa chọn tab Structure trong giao diện này:
Bước 9.
Chúng ta thực hiện stop service MySQL Database.
Chúng ta lựa chọn nút Configure để cấu hình các thông số.
Bước 10.
Cửa sổ Configure MySQL Database hiện ra.
Chúng ta nhận thấy Port 3306 của MySQL.
Chúng ta có thể để nguyên hoặc điều chỉnh theo yêu cầu thực tiễn.
Chúng ta lựa chọn nút Open Conf File để mở file cấu hình my.cnf.
Bước 11.
Nội dung file my.cnf hiện ra.
Chúng ta loại bỏ dòng “skip-name-resolve …”.
Chúng ta lưu lại file này.
Bước 12.
Chúng ta thực hiện cài đặt MySQL Connector/Python trong Anaconda.
Kỹ thuật cơ bản để kết nối và truy xuất Cơ sở dữ liệu MySQL
Bước 1.
Chúng ta tạo mới PyDev Project trong Eclipse IDE và đặt tên là PythonFirstDBProject.
Bước 2.
Chúng ta tạo mới module DBConnection trong package connection.
Bước 3.
Chúng ta định nghĩa các thuộc tính trong phương thức khởi tạo trong module DBConnection.
Ý nghĩa các thuộc tính như sau:
Thuộc tính dbHost và dbPort lưu trữ thông tin về địa chỉ và cổng của MySQL.
Thuộc tính dbName lưu trữ thông tin về tên của database. Ở đây chúng ta sử dụng database firstdb.
Thuộc tính username và password lưu trữ thông tin về tên đăng nhập và mật khẩu để vào được MySQL.
Thuộc tính conn lưu trữ thông tin về kết nối và truy xuất đến cơ sở dữ liệu.
Bước 4.
Chúng ta định nghĩa phương thức đặc tả kết nối đến cơ sở dữ liệu.
Bước 5.
Chúng ta định nghĩa phương thức truy xuất để lấy dữ liệu.
Những kỹ thuật lập trình cần chú ý:
Phương thức này có 02 tham số. Tham số sqlQuery lưu trữ câu truy vấn SQL “SELECT …”. Tham số results là một cấu trúc Dictionary dùng lưu trữ dữ liệu được trả về: (i) từ_khóa lưu trữ dữ liệu của trường khóa chính id trong bảng users; (ii) giá_trị là một danh sách deque có thứ tự trước sau lưu trữ dữ liệu của những trường còn lại trong bảng users.
Bước 1. Chúng ta thực hiện gọi phương thức kết nối: self.getConnection().
Bước 2. Chúng ta thực hiện tạo một phát biểu: cursor = self.Conn.cursor().
Bước 3. Chúng ta thực hiện truy xuất dữ liệu: cursor.execute(sqlQuery).
Bước 4. Chúng ta trả về một resultSet: records = cursor.fetchall().
Bước 5. Chúng ta lần lượt truy xuất từng bộ dữ liệu trong resultSet: for row in records.
Bước 6. Chúng ta thêm bộ dữ liệu hiện tại vào một phần tử trong resultSet. Chú ý: vị trí tương ứng và kiểu dữ liệu của trường tương ứng trong cơ sở dữ liệu.
Bước 7. Chúng ta thực hiện đóng phát biểu và kết nối: cursor.close(); self.Conn.close().
Bước 6.
Chúng ta định nghĩa phương thức thêm mới / chỉnh sửa / xóa bộ dữ liệu.
Bước 7.
Chúng ta thực hiện import những thư viện phù hợp trong module DBConnection để thực hiện định nghĩa các phương thức trên:
Bước 8.
Chúng ta thực hiện tạo thực thể của DBConnection trong module Main.
Bước 9.
Chúng thực hiện thử nghiệm thêm mới bộ dữ liệu.
Bước 10.
Chúng ta kiểm tra trong phpMyAdmin xem bộ dữ liệu mới đã được thêm thành công hay chưa.
Bước 11.
Chúng thực hiện thử nghiệm truy xuất toàn bộ dữ liệu.
Bước 12.
Chúng ta thực thi project để kiểm tra kết quả.
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu một số kỹ thuật cơ bản để kết nối và truy xuất đến Cơ sở dữ liệu MySQL thực hiện bằng ngôn ngữ Python.
Hy vọng rằng chúng ta có thể áp dụng phù hợp những kỹ thuật và chức năng này cho những bài tiếp theo.
Trong nội dung bài này, chúng ta cùng nhau tìm hiểu một số bài toán cơ bản về ước số và bội số:
Tìm ước số chung lớn nhất của hai số tự nhiên.
Tìm bộ số chung nhỏ nhất của hai số tự nhiên.
Phân tích một số tự nhiên thành các thừa số nguyên tố.
Tính số lượng các ước số của một số tự nhiên.
Tính tổng các ước số của một số tự nhiên.
Ước số chung lớn nhất của hai số
Ý tưởng giải thuật
Ước số chung lớn nhất (USCLN) của 2 số được tính theo thuật toán Euclid:
UCLN (a, b) = UCLN (b, (a mod b))
Bước 1.
Chúng ta tạo một PyDev Project trong Eclipse IDE và đặt tên là PythonAlgorithmSecondProject.
Chúng ta tiếp tục tạo package main và module Main.py cùng phương thức main() mặc định.
Bước 2.
Chúng ta tạo package algorithm và module UocBoi.py.
Bước 3.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Python như sau:
Bội số chung nhỏ nhất của hai số
Ý tưởng giải thuật
Bội số chung nhỏ nhất (BSCNN) của hai số được tính theo công thức:
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Python như sau:
Bước 2.
Chúng ta thực hiện thử nghiệm phương thức tinhUCLN() và tinhBCNN() trong module Main.py như sau:
Bước 3.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Phân tích thừa số nguyên tố
Ý tưởng giải thuật
Chúng ta thực hiện chia số N cho các số nguyên tố trong đoạn [2; N].
Với mỗi số nguyên tố đó, đếm số lần mà số N chia hết.
Sau mỗi lần chia cho số i, số N của chúng ta sẽ giảm đi i lần.
Chúng ta dừng quá trình chia khi số chia lớn hơn N.
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Python như sau:
Những kỹ thuật lập trình cần chú ý:
Chúng ta sử dụng kiểu dữ liệu Dictionary của Python để lưu trữ tập hợp không giới hạn các phần tử theo từng cặp <từ_khóa, giá_trị>. Mỗi phần tử là một cặp: từ_khóa là thừa số nguyên tố; giá_trị là số mũ tương ứng với thừa số nguyên tố này.
Bước 2.
Chúng ta thực hiện thử nghiệm phương thức phanTichTSNT() trong module Main.py như sau:
Những kỹ thuật lập trình cần chú ý:
Cách thức để duyệt từng phần tử trong Dictionary để lấy ra được cả từ_khóa và giá_trị là: for (từ_khóa, $giá_trị in dic.items) {}.
Bước 3.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Số các ước số của một số
Ý tưởng giải thuật
Giả sử N được phân tích thành thừa số nguyên tố như sau:
Số các ước số của N là
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Python như sau:
Tổng các ước số của một số
Ý tưởng giải thuật
Tổng các ước của N là
Bước 1.
Chúng ta thực hiện giải thuật bằng ngôn ngữ Python như sau:
Bước 2.
Chúng ta thực hiện thử nghiệm phương thức tinhSoUocSo() và tinhTongUocSo() trong module Main.py như sau:
Bước 3.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu một số giải thuật cơ bản xung quanh ước số và bội số của một số tự nhiên và thực hiện bằng ngôn ngữ Python.
Hy vọng rằng chúng ta có thể áp dụng phù hợp những kỹ thuật và chức năng này cho những bài tiếp theo.
Trong nội dung bài viết này, chúng ta cùng nhau tìm hiểu cách thức mà Java hỗ trợ việc thực hiện những thuật ngữ về Lập trình hướng đối tượng: (i) tính chất trừu tượng – abstraction; (ii) tính chất đa hình – polymorphism; (iii) lớp trừu tượng – abstract class; (iv) giao diện – interface.
Không giống như những ngôn ngữ lập trình khác như Java / C# / PHP, quan điểm của Python là một sự linh động hết sức có thể. Chúng ta có thể tham khảo những đặc trưng của quan điểm Python như sau (https://www.python.org/dev/peps/pep-0020/):
Đẹp thì tốt hơn xấu.
Rõ ràng là tốt hơn so với ngầm.
Đơn giản là tốt hơn phức hợp.
Phức hợp tốt hơn phức tạp.
Bằng phẳng là tốt hơn so với lồng nhau.
Thưa thì tốt hơn dày đặc.
Tính dễ đọc.
Trường hợp đặc biệt không đủ đặc biệt để phá vỡ các quy tắc.
Mặc dù thực tế đánh bại sự tinh khiết.
Lỗi không bao giờ nên âm thầm vượt qua.
Trừ khi im lặng rõ ràng.
Trước sự mơ hồ, hãy từ chối sự cám dỗ để đoán.
Nên có một – và tốt nhất là chỉ có một cách rõ ràng để làm điều đó.
Mặc dù cách đó ban đầu có thể không rõ ràng trừ khi bạn là người Hà Lan.
Bây giờ tốt hơn không bao giờ.
Mặc dù không bao giờ thường tốt hơn * ngay * bây giờ.
Nếu việc thực hiện khó giải thích, đó là một ý tưởng tồi.
Nếu việc thực hiện khó giải thích, đó là một ý tưởng tồi.
Namespaces là một ý tưởng tuyệt vời – hãy làm nhiều hơn nữa!
Đối với tính chất đa hình cũng vậy, Python xem khái niệm abstract class và interface là như nhau và dưới một sự thể hiện duy nhất là abstract class.
Như vậy chúng ta muốn phân tích và thiết kế một chương trình hướng đối tượng càng thuần túy, thì chúng ta phải phân hoạch các class dựa vào tư duy Lập trình hướng đối tượng.
Chúng ta thiết kế một chương trình nhỏ bao gồm các lớp và giao diện như sau:
Lớp trừu tượng: PhuongTienGiaoThong.
Các lớp đối tượng ở tầng dưới thứ hai: PhuongTienDuongBo; PhuongTienDuongThuy; PhuongTienDuongKhong.
Các lớp đối tượng ở tầng dưới cùng: Oto; XeMay; XeDap; TauThuy; Thuyen; MayBay; KhinhKhiCau; ThuyPhiCo.
Giao diện ở cấp cao nhất: HoatDong.
Giao diện ở tầng dưới: CoTheChay; CoTheBay; CoTheBoi.
Thiết kế Lớp trừu tượng
Bước 1.
Chúng ta thực hiện tạo PyDev Project trong Eclipse IDE và đặt tên là PythonOOPThirdProject.
Chúng ta thực hiện tạo package main và file Main.py.
Bước 2.
Chúng ta thực hiện tạo package object.
Chúng ta thực hiện tạo class PhuongTienGiaoThong.
Những điểm cần chú ý:
Cách thức để định nghĩa một lớp đối tượng trong Python là kế thừa từ lớp ABC (viết tắt của Abstract Base Class) trong module abc.
Bước 3.
Chúng ta thực hiện tạo class PhuongTienDuongBo là một dẫn xuất của class PhuongTienGiaoThong.
Bước 4.
Chúng ta thực hiện tạo class PhuongTienDuongThuy là một dẫn xuất của class PhuongTienGiaoThong.
Bước 5.
Chúng ta thực hiện tạo class PhuongTienDuongKhong là một dẫn xuất của class PhuongTienGiaoThong.
Thiết kế Lớp đối tượng
Bước 1.
Chúng ta thực hiện tạo class Oto là một dẫn xuất của class PhuongTienDuongBo.
Bước 2.
Chúng ta thực hiện tạo class XeMay là một dẫn xuất của class PhuongTienDuongBo.
Bước 3.
Chúng ta thực hiện tạo class XeDap là một dẫn xuất của class PhuongTienDuongBo.
Bước 4.
Chúng ta thực hiện tạo class Thuyen là một dẫn xuất của class PhuongTienDuongThuy.
Bước 5.
Chúng ta thực hiện tạo class TauThuy là một dẫn xuất của class PhuongTienDuongThuy.
Bước 6.
Chúng ta thực hiện tạo class MayBay là một dẫn xuất của class PhuongTienDuongKhong.
Bước 7.
Chúng ta thực hiện tạo class KhinhKhiCau là một dẫn xuất của class PhuongTienDuongKhong.
Bước 8.
Chúng ta thực hiện tạo class ThuyPhiCo là một dẫn xuất của class PhuongTienGiaoThong.
Thiết kế Giao diện
Bước 1.
Chúng ta thực hiện tạo package action.
Chúng ta thực hiện tạo abstract class CoTheChay đóng vai trò như một interface.
Bước 2.
Chúng ta thực hiện tạo abstract class CoTheBoi đóng vai trò như một interface.
Bước 3.
Chúng ta thực hiện tạo abstract class CoTheBay đóng vai trò như một interface.
Bước 4.
Chúng ta thực hiện tạo abstract class HoatDong đóng vai trò như một interface, là class cơ sở của các class: CoTheChay; CoTheBay; CoTheBoi.
Thiết kế Tính đa hình thứ nhất
Bước 1.
Chúng ta đặc tả những đặc trưng của abstract class PhuongTienGiaoThong:
Thuộc tính: soLuongBanhXe; soLuongChoNgoi.
Những phương thức get / set.
Phương thức trừu tượng: gioiThieu().
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienGiaoThong trên cây gia phả.
Những điểm cần chú ý:
Chúng ta sử dụng decorator @abstractmethod trong module abc để định nghĩa một phương thức trừu tượng.
Bước 2.
Chúng ta đặc tả những đặc trưng của class PhuongTienDuongBo:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 01 thuộc tính riêng biệt: loaiDongCo.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiDongCo.
Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongBo trên cây gia phả.
Bước 3.
Chúng ta đặc tả những đặc trưng của class PhuongTienDuongKhong:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 02 thuộc tính riêng biệt: soLuongCanh; soLuongQuat.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính soLuongCanh; soLuongQuat.
Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongKhong trên cây gia phả.
Bước 4.
Chúng ta đặc tả những đặc trưng của class PhuongTienDuongThuy:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 01 thuộc tính riêng biệt: loaiBanhLai.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiBanhLai.
Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongThuy trên cây gia phả.
Bước 5.
Chúng ta đặc tả những đặc trưng của class Oto:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 6.
Chúng ta đặc tả những đặc trưng của class XeMay:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 7.
Chúng ta đặc tả những đặc trưng của class XeDap:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 8.
Chúng ta đặc tả những đặc trưng của class MayBay:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongKhong.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 9.
Chúng ta đặc tả những đặc trưng của class KhinhKhiCau:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongKhong.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 10.
Chúng ta đặc tả những đặc trưng của class TauThuy:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongThuy.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 11.
Chúng ta đặc tả những đặc trưng của class Thuyen:
Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongThuy.
Phương thức. Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 12.
Chúng ta đặc tả những đặc trưng của class ThuyPhiCo:
Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 02 thuộc tính riêng biệt: loaiBanhLai; soLuongCanh.
Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiBanhLai; soLuongCanh.
Kế thừa và đặc tả lại phương thức gioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.
Bước 13.
Chúng ta thực hiện thử nghiệm tính đa hình như bên dưới.
Chúng ta có thể nhận thấy những điểm rất rõ ở đây là:
Thực thể của đối tượng nào thì sẽ tự biết mình là ai.
Và như vậy sẽ tự thực hiện một cách chính xác phương thức gioiThieu() cũng như các phương thức get / set của các thuộc tính được đặc tả trong lớp trừu tượng PhuongTienGiaoThong.
Bước 14.
Kết quả thực hiện thử nghiệm đa hình thứ nhất như sau:
Thiết kế Tính đa hình thứ hai
Bước 1.
Chúng ta định nghĩa phương thức trừu tượng thongBao() trong class cơ sở HoatDong.
Bước 2.
Chúng ta định nghĩa class CoTheChay kế thừa từ class HoatDong:
Kế thừa việc định nghĩa các phương thức trừu tượng từ class HoatDong.
Định nghĩa phương thức trừu tượng riêng biệt: chay().
Bước 3.
Chúng ta định nghĩa class CoTheBoi kế thừa từ class HoatDong:
Kế thừa việc định nghĩa các phương thức trừu tượng từ class HoatDong.
Định nghĩa phương thức trừu tượng riêng biệt: boi().
Bước 4.
Chúng ta định nghĩa class CoTheBay kế thừa từ class HoatDong:
Kế thừa việc định nghĩa các phương thức trừu tượng từ class HoatDong.
Định nghĩa phương thức trừu tượng riêng biệt: bay().
Bước 5.
Chúng ta điều chỉnh class PhuongTienDuongBo để thuộc phạm vi ảnh hưởng của class CoTheChay:
Bước 6.
Chúng ta điều chỉnh class PhuongTienDuongThuy để thuộc phạm vi ảnh hưởng của class CoTheBoi:
Bước 7.
Chúng ta điều chỉnh class PhuongTienDuongKhong để thuộc phạm vi ảnh hưởng của class CoTheBay:
Bước 8.
Chúng ta điều chỉnh class ThuyPhiCo để thuộc phạm vi ảnh hưởng của class CoTheChay và CoTheBoi.
Bước 9.
Chúng ta điều chỉnh class Oto:
Bước 10.
Chúng ta điều chỉnh class XeMay:
Bước 11.
Chúng ta điều chỉnh class XeDap:
Bước 12.
Chúng ta điều chỉnh class MayBay:
Bước 13.
Chúng ta điều chỉnh class KhinhKhiCau:
Bước 14.
Chúng ta điều chỉnh class TauThuy:
Bước 15.
Chúng ta điều chỉnh class Thuyen:
Bước 16.
Chúng ta điều chỉnh lại ví dụ về tính đa hình như bên dưới.
Chúng ta cần kiểm tra một chút để biết thực thể của đối tượng nào bằng cách sử dụng từ khóa isinstance.
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu sự hỗ trợ của Python trong việc thực hiện tính chất đa hình trong Lập trình hướng đối tượng.
Hi vọng với bài này thì chúng ta đã có cái nhìn tổng quát hơn về cả 04 tính chất đặc trưng nhất của Lập trình hướng đối tượng.
Trong nội dung bài này, chúng ta cùng nhau tìm hiểu tính chất kế thừa trong tư duy Lập trình hướng đối tượng.
Nhắc lại đặc điểm của tính chất kế thừa như sau:
Đặc tính này cho phép một đối tượng có thể có sẵn các đặc tính mà đối tượng khác đã có thông qua kế thừa.
Điều này cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại.
Xây dựng lớp đối tượng HinhChuNhat
Bước 1.
Chúng ta tạo một PyDev Project trong Eclipse IDE và đặt tên là PythonOOPSecondProject.
Chúng ta tiếp tục tạo package main và module Main.py cùng phương thức main() mặc định.
Bước 2.
Chúng ta tạo package object và module HinhChuNhat.py.
Bước 3.
Chúng ta định nghĩa 02 thuộc tính cơ bản của một hình chữ nhật:
Những kỹ thuật lập trình cần chú ý:
Chúng ta áp dụng cách tiếp cận định nghĩa hình thức properties bằng cách sử dụng decorator @property.
Khác với nhóm ngôn ngữ Java / Csharp, Python không cung cấp một cách tường minh để định nghĩa các thuộc tính của một lớp đối tượng và do vậy cũng không thể định nghĩa tường minh việc kế thừa các thuộc tính.
Chúng ta sẽ hiện thực việc kế thừa các thuộc tính thông qua các properties trên.
Bước 4.
Chúng ta định nghĩa các constructor cho lớp đối tượng:
Bước 5.
Chúng ta định nghĩa các phương thức tính chu vi, diện tích và đường chéo hình chữ nhật:
Những kỹ thuật lập trình cần chú ý:
Có lẽ cũng cần nhắc lại một chút về công thức tính đường chéo ở đây: (đường_chéo)^2 = (chiều_dài)^2 + (chiều_rộng)^2.
Xây dựng lớp đối tượng HinhVuong
Bước 1.
Chúng ta tạo module HinhVuong.py.
Những kỹ thuật lập trình cần chú ý:
Trong ví dụ ở đây, chúng ta sử dụng cách thức của Python để đặc tả sự kế thừa: xác định tên của lớp cơ sở là class HinhChuNhat của module HinhChuNhat.py bên trong cặp dấu “()” bên cạnh tên của lớp dẫn xuất là class HinhVuong của module HinhVuong.py.
Chú ý rằng trong mỗi module abc.py, chúng ta có thể định nghĩa nhiều class khác nhau. Chúng ta được khuyến khích là mỗi module abc.py chỉ nên định nghĩa một class để dễ quản lý, và tốt nhất là trùng tên với module.
Bước 2.
Chúng ta định nghĩa các constructor cho lớp đối tượng:
Những kỹ thuật lập trình cần chú ý:
Trong constructor cho class HinhVuong, chúng ta có thể thực thi các tác vụ khởi tạo giá trị mặc định nào đó cho riêng class HinhVuong.
Nếu chúng ta muốn gọi constructor của lớp cơ sở để thực thi, ví dụ ở đây là class HinhChuNhat, chúng ta sử dụng phương thức super() và truyền tham số tương ứng với constructor cho class HinhChuNhat.
Bước 3.
Chúng ta thực hiện kế thừa và điều chỉnh phương thức setter:
Những kỹ thuật lập trình cần chú ý:
Trong ví dụ ở đây, chúng ta cần điều chỉnh phương thức setter vì trong hình vuông thì chiều dài và chiều rộng là bằng nhau (nên được gọi chung là cạnh).
Cú pháp để thực hiện kế thừa, mở rộng và điều chỉnh properties được thể hiện rõ nét trong ví dụ này. Chúng ta chỉ cần áp dụng tương tự cho những bài tập khác.
Chú ý rằng chúng ta sử dụng tên của lớp cơ sở, ở đây là HinhChuNhat, để gọi đến properties đã được định nghĩa ở lớp cơ sở. Sau đó chúng ta gọi đến phương thức fset() để thực hiện điều chỉnh thông tin.
Bước 4.
Chúng ta thực hiện kế thừa và điều chỉnh phương thức tinhDuongCheo():
Những kỹ thuật lập trình cần chú ý:
Chúng ta không cần điều chỉnh các phương thức về tính chu vi và diện tích vì thực ra công thức là như nhau. Do vậy trong class HinhVuong chúng ta không đặc tả lại mà kế thừa hoàn toàn từ class HinhChuNhat đối với 02 phương thức tinhChuVi() và tinhDienTich().
Đối với tác vụ tính đường chéo, chúng ta có 03 lựa chọn. Lựa chọn thứ nhất. Tương tự như 02 phương thức tinhChuVi() và tinhDienTich(), chúng ta không đặc tả lại mà kế thừa hoàn toàn từ class HinhChuNhat. Lựa chọn thứ hai. Chúng ta thực hiện kế thừa lại bằng cách gọi phương thức của class HinhChuNhat để thực thi: super().tinhDuongCheo(). Lựa chọn thứ ba. Chúng ta thực thi theo công thức thu gọn dành riêng cho hình vuông: (đường_chéo) ^2 = 2 * (cạnh)^2.
Thử nghiệm chương trình
Bước 1.
Chúng ta thực hiện thử nghiệm tạo mới 01 hình chữ nhật, 02 hình vuông và tính chu vi, diện tích, đường chéo:
Bước 2.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu tính chất kế thừa trong Lập trình hướng đối tượng.
Chúng ta đã cùng nhau thực hiện một ví dụ nhỏ về tính chất kế thừa với ngôn ngữ Python.
Trong các bài tiếp theo, chúng ta sẽ tiếp tục tìm hiểu những kiến thức khác xung quanh lập trình hướng đối tượng.
Lập trình hướng đối tượng (tiếng Anh: Object-oriented programming, viết tắt: OOP) là một mô hình kiến trúc lập trình dựa trên khái niệm “công nghệ đối tượng”, mà trong đó, đối tượng chứa đựng các dữ liệu: (i) thuộc tính của đối tượng; (ii) phương thức để thực thi các hành động của đối tượng.
OOP được xem là giúp tăng năng suất, đơn giản hóa độ phức tạp khi bảo trì cũng như mở rộng phần mềm bằng cách cho phép lập trình viên tập trung vào các đối tượng phần mềm ở bậc cao hơn.
Một số khái niệm cơ bản
Khái niệm đầu tiên là “đối tượng”, được hiểu như là 1 thực thể: người, vật hoặc 1 bảng dữ liệu, . . .
Một đối tượng bao gồm 2 thông tin chính:
Thuộc tính. Là những thông tin, đặc điểm của đối tượng. Ví dụ: một hình chữ nhật sẽ có chiều dài, chiều rộng, . . .
Phương thức. Là những thao tác, hành động mà đối tượng đó có thể thực hiện. Ví dụ: một hình chữ nhật sẽ có thao tác tính chu vi, diện tích, . . .
Khái niệm thứ hai là “lớp”, được hiểu như là một khuôn mẫu mà từng đối tượng là một thể hiện cụ thể dựa trên khuôn mẫu đó.
Ví dụ một lớp hình chữ nhật sẽ định nghĩa: (i) các thuộc tính chiều dài / chiều rộng; (ii) các phương thức tính chu vi, tính diện tích. Còn từng đối tượng hình chữ nhật sẽ có số đo cụ thể cho từng thuộc tính cũng như chu vi và diện tích riêng.
Các tính chất của lập trình hướng đối tượng
Tính đóng gói (encapsulation) và che giấu thông tin (information hiding):
Tính chất này không cho phép tác nhân bên ngoài thay đổi trạng thái nội tại của một đối tượng.
Chỉ có các phương thức nội tại của đối tượng cho phép thay đổi trạng thái của nó.
Đây là tính chất đảm bảo sự toàn vẹn của đối tượng.
Tính trừu tượng (abstraction):
Là phương pháp trừu tượng hóa định nghĩa lên những hành động, tính chất của loại đối tượng nào đó cần phải có.
Mỗi đối tượng có thể hoàn tất các công việc một cách nội bộ, báo cáo, thay đổi trạng thái của nó và liên lạc với các đối tượng khác mà không cần cho biết làm cách nào đối tượng tiến hành được các thao tác.
Tính chất này thường được gọi là sự trừu tượng của dữ liệu.
Tính kế thừa (inheritance):
Đặc tính này cho phép một đối tượng có thể có sẵn các đặc tính mà đối tượng khác đã có thông qua kế thừa.
Điều này cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại.
Tính đa hình (polymorphism):
Thể hiện thông qua việc gửi các thông điệp (message).
Việc gửi các thông điệp này có thể so sánh như việc gọi các phương thức bên trong của một đối tượng.
Các phương thức dùng trả lời cho một thông điệp sẽ tùy theo đối tượng mà thông điệp đó được gửi tới sẽ có phản ứng khác nhau.
Xây dựng lớp đối tượng độc lập
Trong nội dung bài này, chúng ta cùng tìm hiểu cách xây dựng một lớp đối tượng độc lập cùng với tính chất đóng gói (encapsulation) bằng ngôn ngữ Python.
Bước 1.
Chúng ta tạo một PyDev Project trong Eclipse IDE và đặt tên là PythonOOPFirstProject.
Chúng ta tiếp tục tạo package main và module Main.py cùng phương thức main() mặc định.
Bước 2.
Chúng ta tạo package object và module HinhChuNhat.py.
Những kỹ thuật lập trình cần chú ý:
Như đã trình bày ở phần Giới thiệu về Tính đóng gói (encapsulation) và che giấu thông tin (information hiding). Mỗi package có thể được xem như là một hình thức để gom nhóm các lớp đối tượng có cùng chung những đặc điểm nào đó.
Python là một ngôn ngữ lập trình rất linh động và hỗ trợ nhiều phong cách lập trình khác nhau. Chúng ta có thể tự do lựa chọn việc có đặt một module vào bên trong một package hay không. Tuy nhiên, để dễ quản lý một chương trình phần mềm lớn, chúng ta nên phân hoạch các module vào trong những package theo tư duy hướng đối tượng.
Trong ví dụ hiện tại, chúng ta có thể đặt tên package là object (nghĩa là đối tượng nói chung) hoặc shape (nghĩa là hình vẽ nói chung).
Bước 3.
Khác với nhóm ngôn ngữ Java / Csharp, Python không cung cấp một cách tường minh để định nghĩa các thuộc tính của một lớp đối tượng. Về cơ bản, mọi thuộc tính hay phương thức trong một module của Python đều là public và được truy xuất tự do từ các module khác. Điều này có vẻ không thực sự phù hợp theo tư duy lập trình hướng đối tượng.
Để phù hợp Tính đóng gói (encapsulation) và che giấu thông tin (information hiding) trong Lập trình hướng đối tượng, Python cung cấp 02 cách tiếp cận để định nghĩa các phương thức đặc biệt truy xuất và điều chỉnh dữ liệu, hay còn được gọi là các getter và setter.
Cách tiếp cận thứ nhất:
Định nghĩa cặp phương thức get / set để truy xuất và điều chỉnh thông tin cho thuộc tính tương ứng.
Xác lập tính chất ẩn của cặp phương thức này bằng cách thêm “__” vào phía trước tên phương thức. Thực ra chúng ta không bắt buộc phải thực hiện bước này. Chúng ta có thể sử dụng hai phương thức này ở các module khác. Nhưng chúng ta sẽ thấy rằng có đến 02 cách truy xuất và điều chỉnh dữ liệu: (i) thông qua một hình thức được gọi là properties; (ii) thông qua hai phương thức này. Và như vậy sẽ không phù hợp với triết lý của Python là chỉ nên có một cách thực hiện một tác vụ.
Định nghĩa hình thức properties bằng cách sử dụng phương thức đặc biệt là property(). Phương thức này có 04 tham số lần lượt là các phương thức được định nghĩa với ý nghĩa: (i) get() để truy xuất thuộc tính; (ii) set() để điều chỉnh thông tin thuộc tính; (iii) del() để xóa thông tin thuộc tính; (iv) doc() để tạo một mô tả cho thuộc tính. Ở đây chúng ta chỉ cần đến 02 tham số đầu tiên là get / set.
Chúng ta có thể sử dụng các properties này như là một thuộc tính của đối tượng. Theo quy tắc chung, tên của từng properties nên được đặt trùng với tên của thuộc tính, chỉ có một điểm khác là chữ cái đầu viết hoa.
Cách tiếp cận thứ hai:
Định nghĩa hình thức properties bằng cách sử dụng decorator @property.
Decorators là công cụ rất mạnh mẽ và hữu ích trong Python vì nó cho phép các lập trình viên sửa đổi hành vi của phương thức hoặc thuộc tính. Decorators cho phép chúng ta bọc một phương thức khác để mở rộng hành vi của phương thức được bọc, mà không sửa đổi vĩnh viễn. Chúng ta sẽ dần dần tìm hiểu kỹ thuật lập trình này trong những bài tiếp theo.
Bước 4.
Chúng ta định nghĩa constructor cho lớp đối tượng.
Những kỹ thuật lập trình cần chú ý:
Constructor là một dạng đặc biệt của phương thức, được sử dụng để khởi tạo các đối tượng.
Constructor được gọi tại thời điểm tạo đối tượng. Nó khởi tạo các giá trị để cung cấp dữ liệu cho các đối tượng, đó là lý do tại sao nó được gọi là constructor.
Khác với nhóm ngôn ngữ Java / C#, Python chỉ cung cấp một phương thức constructor duy nhất là __init__(). Chúng ta sẽ chủ động quyết định xem có để tham số cho constructor hay không. Cách thức được sử dụng ở đây là gán sẵn giá trị tên_tham_số = None và kiểm tra.
Từ khóa self giúp chúng ta liên hệ đến thuộc tính hoặc phương thức nội tại của lớp đối tượng. Chúng ta sử dụng từ khóa này để phân biệt khi muốn định nghĩa các biến có cùng tên với các thuộc tính hoặc phương thức nội tại của lớp.
Đối với thuộc tính chieuDai, chúng ta đã sử dụng cách tiếp cận thứ nhất bên trên để định nghĩa properties chieuDai. Do vậy chúng ta không cần định nghĩa tường minh thuộc tính này mà chỉ cần gọi phương thức ẩn __setChieuDai().
Đối với thuộc tính chieuRong, chúng ta đã sử dụng cách tiếp cận thứ hai bên trên để định nghĩa properties ChieuRong. Do vậy chúng ta định nghĩa tường minh thuộc tính ẩn __chieuRong.
Bước 5.
Chúng ta định nghĩa các phương thức tính chu vi và diện tích hình chữ nhật:
Bước 6.
Chúng ta thực hiện thử nghiệm tạo mới 02 hình chữ nhật và tính chu vi, diện tích:
Những kỹ thuật lập trình cần chú ý:
Để truy xuất đến những lớp đối tượng ở một package khác, chúng ta sử dụng từ khóa from và import. Ví dụ ở đây là from object import HinhChuNhat.
Chúng ta khởi tạo một đối tượng thực bằng cách gọi tên của module và tên của lớp bên trong, ví dụ ở đây là MyClass(). Tùy thuộc vào tham số được truyền thì constructor __init__() sẽ thực thi việc khởi tạo giá trị tương ứng cho các thuộc tính.
Ví dụ ở đây. Đối tượng hinhChuNhatA được khởi tạo với constructor mặc định không có tham số. Như vậy sẽ sử dụng properties để điều chỉnh thông tin cho thuộc tính của đối tượng. Đối tượng hinhChuNhatB được khởi tạo với constructor có tham số.
Bước 7.
Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:
Tổng kết
Trong bài này, chúng ta đã cùng nhau tìm hiểu những kiến thức cơ bản về lớp đối tượng cũng như những tính chất về lập trình hướng đối tượng.
Chúng ta đã cùng nhau thực hiện một ví dụ nhỏ về lớp đối tượng với ngôn ngữ Python.
Trong các bài tiếp theo, chúng ta sẽ tiếp tục tìm hiểu những kiến thức khác xung quanh lập trình hướng đối tượng.