Menu
CoddyTech

Ẩn thông tin

Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 36 trên 104.

Ẩn thông tin không chỉ đơn thuần là dùng các từ chỉ định quyền truy cập. Đây là một nguyên tắc thiết kế, trong đó bạn ẩn không chỉ dữ liệu mà còn cả chi tiết triển khai về cách lớp hoạt động bên trong.

Mục tiêu là chỉ cho người dùng lớp của bạn thấy những gì họ cần biết, đồng thời ẩn mọi thứ khác. Nhờ vậy, bạn có thể thay đổi cách triển khai nội bộ mà không ảnh hưởng đến code sử dụng lớp của bạn:

class Temperature {
    double kelvin;    // Cách biểu diễn nội bộ, chi tiết được ẩn đi
    
public:
    void setCelsius(double c) {
        kelvin = c + 273.15;    // Phép chuyển đổi được ẩn khỏi người dùng
    }
    
    double getCelsius() const {
        return kelvin - 273.15;
    }
    
    double getFahrenheit() const {
        return (kelvin - 273.15) * 9.0/5.0 + 32;
    }
};

Người dùng lớp này không biết (và cũng không cần biết) rằng nhiệt độ được lưu trữ nội bộ theo đơn vị Kelvin. Nếu sau này bạn quyết định lưu nhiệt độ theo đơn vị Celsius, bạn chỉ cần thay đổi phần triển khai riêng tư, còn giao diện công khai vẫn giữ nguyên.

Việc tách biệt giao diện với cách triển khai mang lại nhiều lợi ích: giảm độ phức tạp cho người dùng lớp của bạn, ngăn việc sử dụng nhầm dữ liệu nội bộ và giúp bạn dễ bảo trì code hơn. Khi ẩn các chi tiết nội bộ, bạn có thể tự do tối ưu hóa hoặc tái cấu trúc mà không làm hỏng code hiện có phụ thuộc vào lớp của bạn.

challenge icon

Thử thách

Dễ

Hãy xây dựng một lớp Distance để minh họa tính đóng gói thông tin bằng cách lưu trữ khoảng cách nội bộ theo centimet, đồng thời cung cấp giao diện rõ ràng để làm việc với các đơn vị khác nhau. Người dùng lớp của bạn không cần biết (hoặc quan tâm) khoảng cách được lưu trữ nội bộ như thế nào: họ chỉ cần làm việc với đơn vị thuận tiện cho mình.

Bạn sẽ tạo hai tệp để sắp xếp code:

  • Distance.h: Định nghĩa lớp Distance, lớp này ẩn cách biểu diễn nội bộ nhưng cung cấp giao diện công khai linh hoạt. Bên trong, hãy lưu khoảng cách theo centimet (dưới dạng double). Đây là chi tiết triển khai được ẩn đi. Giao diện công khai cần cho phép người dùng:
    • Đặt khoảng cách bằng setMeters(double m), setCentimeters(double cm) hoặc setKilometers(double km)
    • Lấy khoảng cách bằng getMeters(), getCentimeters() hoặc getKilometers(): tất cả đều phải là phương thức const
    • Cộng hai khoảng cách bằng add(const Distance& other), hàm này trả về một đối tượng Distance mới

    Thêm hàm khởi tạo mặc định để khởi tạo khoảng cách bằng không. Ẩn logic chuyển đổi bên trong các phương thức: người dùng chỉ cần gọi setKilometers(5) và getMeters() mà không cần bận tâm đến định dạng lưu trữ nội bộ.

  • main.cpp: Minh họa cách người dùng có thể làm việc với lớp mà không cần biết cách biểu diễn nội bộ. Đọc hai giá trị khoảng cách từ đầu vào: giá trị đầu tiên theo mét, giá trị thứ hai theo kilômét. Sau đó:
    • Tạo một đối tượng Distance và đặt giá trị bằng khoảng cách theo mét
    • In ra "In meters: <value> m"
    • In ra "In centimeters: <value> cm"
    • In ra "In kilometers: <value> km"
    • Tạo đối tượng Distance thứ hai và đặt giá trị bằng khoảng cách theo kilômét
    • Cộng hai khoảng cách với nhau và lưu kết quả
    • In ra "Combined in meters: <value> m"

Ưu điểm của tính đóng gói thông tin là sau này bạn có thể đổi cách lưu trữ nội bộ từ centimet sang milimet (hoặc bất kỳ đơn vị nào khác) mà không cần thay đổi cách người dùng tương tác với lớp. Giao diện công khai vẫn ổn định ngay cả khi phần triển khai thay đổi.

Định dạng tất cả giá trị đầu ra với hai chữ số thập phân bằng std::fixed và std::setprecision(2) từ <iomanip>. Chuyển chuỗi đầu vào thành số thực bằng std::stod().

Quy đổi tham khảo: 1 mét = 100 centimet, 1 kilômét = 1000 mét.

Tự làm thử

#include <iostream>
#include <string>
#include <iomanip>
#include "Distance.h"

using namespace std;

int main() {
    // Đọc các giá trị đầu vào
    string metersInput, kmInput;
    cin >> metersInput;  // Giá trị đầu tiên tính bằng mét
    cin >> kmInput;      // Giá trị thứ hai tính bằng kilômét
    
    // Chuyển các chuỗi thành số thực kiểu double bằng std::stod()
    double metersValue = stod(metersInput);
    double kmValue = stod(kmInput);
    
    // Định dạng đầu ra
    cout << fixed << setprecision(2);
    
    // TODO: Tạo đối tượng Distance đầu tiên và gán giá trị tính bằng mét
    
    // TODO: In ra "In meters: <value> m"
    
    // TODO: In ra "In centimeters: <value> cm"
    
    // TODO: In ra "In kilometers: <value> km"
    
    // TODO: Tạo đối tượng Distance thứ hai và gán giá trị tính bằng kilômét
    
    // TODO: Cộng hai khoảng cách bằng phương thức add()
    
    // TODO: In ra "Combined in meters: <value> m"
    
    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C++ online