Menu
CoddyTech

Thuộc tính để đóng gói

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 32 trên 70.

Thuộc tính là công cụ chính để triển khai tính đóng gói trong C#. Thay vì cho phép truy cập trực tiếp vào các trường, bạn bọc chúng bằng thuộc tính để kiểm soát cách truy cập và thay đổi dữ liệu.

Mẫu này kết hợp một trường riêng tư với một thuộc tính công khai có phần kiểm tra hợp lệ hoặc logic trong các bộ truy cập:

public class Temperature
{
    private double celsius;
    
    public double Celsius
    {
        get { return celsius; }
        set
        {
            if (value < -273.15)
                celsius = -273.15;  // Giới hạn thấp nhất là độ không tuyệt đối
            else
                celsius = value;
        }
    }
}

Giờ đây, code bên ngoài không thể đặt nhiệt độ bất khả thi. Thuộc tính đóng vai trò như người gác cổng, đảm bảo đối tượng của bạn luôn ở trạng thái hợp lệ. Đây là tính đóng gói trong thực tế: dữ liệu bên trong được bảo vệ nhưng vẫn có thể truy cập thông qua một giao diện có kiểm soát.

Bạn cũng có thể dùng thuộc tính để tính giá trị hoặc kích hoạt tác dụng phụ:

public double Fahrenheit
{
    get { return celsius * 9 / 5 + 32; }
    set { celsius = (value - 32) * 5 / 9; }
}

Bên ngoài thấy hai thuộc tính, nhưng bên trong chỉ có một trường. Thuộc tính cho phép bạn thay đổi chi tiết triển khai mà không làm hỏng code sử dụng lớp của bạn, đây là lợi ích quan trọng của việc đóng gói đúng cách.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống quản lý hàng tồn kho dùng thuộc tính để bảo vệ tính toàn vẹn của dữ liệu. Bạn sẽ tạo một lớp trong đó giá không bao giờ âm và số lượng luôn nằm trong giới hạn hợp lệ, qua đó cho thấy thuộc tính đóng vai trò như người gác cổng cho dữ liệu của bạn.

Bạn sẽ sắp xếp code trong hai tệp:

  • Product.cs: Tạo một lớp Product trong không gian tên Inventory, lớp này quản lý thông tin sản phẩm và kiểm tra tính hợp lệ thông qua các thuộc tính. Sản phẩm của bạn cần có:
    • Một trường riêng tư price (số thập phân) cùng thuộc tính công khai Price, đảm bảo giá không bao giờ thấp hơn 0. Nếu ai đó cố đặt giá âm, giá trị được lưu sẽ là 0
    • Một trường riêng tư quantity (số nguyên) cùng thuộc tính công khai Quantity, giữ giá trị trong khoảng từ 0 đến 1000. Giá trị dưới 0 trở thành 0, giá trị trên 1000 trở thành 1000
    • Một thuộc tính công khai tự động triển khai Name (chuỗi)
    • Một thuộc tính chỉ đọc được tính toán TotalValue, trả về Price * Quantity
    Thêm một hàm khởi tạo nhận tên, giá và số lượng theo đúng thứ tự đó, rồi thiết lập mọi giá trị thông qua các thuộc tính để áp dụng quy tắc kiểm tra tính hợp lệ.
  • Program.cs: Trong tệp chính, hãy tạo một Product bằng các giá trị đầu vào. Sau đó, thử thay đổi giá và số lượng bằng các giá trị đầu vào bổ sung có thể không hợp lệ. In trạng thái sản phẩm sau khi tạo và sau mỗi lần thay đổi để xem các thuộc tính bảo vệ dữ liệu như thế nào.

Bạn sẽ nhận năm giá trị đầu vào:

  • Tên sản phẩm
  • Giá ban đầu (số thập phân)
  • Số lượng ban đầu (số nguyên)
  • Giá mới cần đặt (số thập phân, có thể âm)
  • Số lượng mới cần đặt (số nguyên, có thể nằm ngoài phạm vi)

In đầu ra theo định dạng sau:

After creation:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
After modifications:
{Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}

Ví dụ, nếu các giá trị đầu vào là Laptop, 999.99, 50, -100 và 1500, đầu ra sẽ là:

After creation:
Laptop: Price=999.99, Qty=50, Total=49999.50
After modifications:
Laptop: Price=0, Qty=1000, Total=0

Hãy chú ý cách giá âm trở thành 0 và số lượng 1500 được giới hạn ở mức 1000. Các thuộc tính đang bảo vệ đối tượng khỏi những trạng thái không hợp lệ. Đây chính là tính đóng gói đang hoạt động!

Tự làm thử

using System;
using Inventory;

class Program
{
    public static void Main(string[] args)
    {
        // Đọc các giá trị đầu vào
        string name = Console.ReadLine();
        decimal initialPrice = Convert.ToDecimal(Console.ReadLine());
        int initialQuantity = Convert.ToInt32(Console.ReadLine());
        decimal newPrice = Convert.ToDecimal(Console.ReadLine());
        int newQuantity = Convert.ToInt32(Console.ReadLine());

        // TODO: Tạo một Product bằng các giá trị ban đầu
        
        // TODO: In ra trạng thái của sản phẩm sau khi tạo
        Console.WriteLine("After creation:");
        // Định dạng in ra: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
        
        // TODO: Cập nhật giá và số lượng bằng các giá trị mới
        
        // TODO: In ra trạng thái của sản phẩm sau khi cập nhật
        Console.WriteLine("After modifications:");
        // Định dạng in ra: {Name}: Price={Price}, Qty={Quantity}, Total={TotalValue}
    }
}
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