Dữ liệu instance và dữ liệu tĩnh
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 15 trên 70.
Bây giờ bạn đã hiểu về các thành viên tĩnh, hãy cùng làm rõ khi nào nên dùng dữ liệu của instance và khi nào nên dùng dữ liệu tĩnh. Lựa chọn này quyết định cách lớp lưu trữ và chia sẻ thông tin.
Dữ liệu của từng đối tượng thuộc về riêng từng đối tượng. Mỗi đối tượng có bản sao riêng, và những thay đổi ở một đối tượng không ảnh hưởng đến các đối tượng khác:
public class BankAccount
{
public string Owner { get; set; } // Instance, riêng cho từng tài khoản
public decimal Balance { get; set; } // Instance, riêng cho từng tài khoản
}Mỗi BankAccount có chủ sở hữu và số dư riêng. Điều đó hợp lý vì các tài khoản khác nhau có số tiền khác nhau và thuộc về những người khác nhau.
Dữ liệu tĩnh thuộc về chính lớp đó và được chia sẻ giữa tất cả các đối tượng:
public class BankAccount
{
public static decimal InterestRate = 0.05m; // Tĩnh: dùng chung cho tất cả tài khoản
public static int TotalAccounts = 0; // Tĩnh: theo dõi tất cả tài khoản
public string Owner { get; set; }
public decimal Balance { get; set; }
}Lãi suất áp dụng như nhau cho mọi tài khoản, nên để nó ở dạng tĩnh là hợp lý. Bộ đếm tổng số tài khoản theo dõi thông tin chung của lớp, không phải dữ liệu của từng tài khoản.
Một quy tắc đơn giản: nếu dữ liệu mô tả một đối tượng cụ thể, hãy biến nó thành thuộc tính của instance. Nếu dữ liệu mô tả cả lớp hoặc cần được chia sẻ, hãy đặt nó là static. Dùng sai lẫn lộn sẽ gây ra bug, khiến dữ liệu thay đổi ngoài dự kiến giữa các đối tượng hoặc không thể truy cập khi cần.
Thử thách
DễHãy xây dựng bộ theo dõi phiên chơi game để thể hiện sự khác biệt giữa dữ liệu riêng của từng người chơi và dữ liệu được chia sẻ trong toàn bộ game.
Bạn sẽ tạo hai tệp để sắp xếp code:
Player.cs: Định nghĩa lớpPlayertrong không gian tênGameSession. Mỗi người chơi cóUsername(chuỗi) vàScore(số nguyên) riêng, các giá trị này khác nhau ở mỗi người chơi. Lớp cũng cần theo dõi thông tin áp dụng cho tất cả người chơi: trường tĩnhGameName(chuỗi) lưu tên game mà mọi người đang chơi và trường tĩnhTotalPlayers(số nguyên) đếm số người chơi đã tham gia. Thêm hàm khởi tạo nhận tên người chơi và điểm số ban đầu, đồng thời tự động tăng tổng số người chơi. Thêm phương thức tĩnhSetGameName(string name)để thiết lập tên game.Program.cs: Trong tệp chính, thiết lập game và tạo người chơi dựa trên đầu vào. Trước tiên, hãy đặt tên game, sau đó tạo hai người chơi và hiển thị thông tin riêng của họ cùng dữ liệu chung của game.
Bạn sẽ nhận năm đầu vào:
- Tên game
- Tên người chơi thứ nhất
- Điểm số ban đầu của người chơi thứ nhất
- Tên người chơi thứ hai
- Điểm số ban đầu của người chơi thứ hai
In đầu ra theo định dạng này:
Game: {GameName}
Player: {Username}, Score: {Score}
Player: {Username}, Score: {Score}
Total Players: {TotalPlayers}Ví dụ: nếu đầu vào là BattleArena, DragonSlayer, 1500, ShadowNinja và 2200, đầu ra sẽ là:
Game: BattleArena
Player: DragonSlayer, Score: 1500
Player: ShadowNinja, Score: 2200
Total Players: 2Hãy cân nhắc kỹ dữ liệu nào nên thuộc về từng đối tượng (khác nhau ở mỗi người chơi) và dữ liệu nào nên là dữ liệu tĩnh (được chia sẻ giữa tất cả người chơi). Tên game và tổng số người chơi mô tả cả phiên chơi, còn tên người chơi và điểm số là riêng của từng người.
Tự làm thử
using System;
namespace GameSession
{
class Program
{
public static void Main(string[] args)
{
// Đọc dữ liệu đầu vào
string gameName = Console.ReadLine();
string username1 = Console.ReadLine();
int score1 = Convert.ToInt32(Console.ReadLine());
string username2 = Console.ReadLine();
int score2 = Convert.ToInt32(Console.ReadLine());
// TODO: Đặt tên trò chơi bằng phương thức tĩnh
// TODO: Tạo hai đối tượng Player từ dữ liệu đầu vào
// TODO: In đầu ra theo đúng định dạng yêu cầu
// Game: {GameName}
// Player: {Username}, Score: {Score}
// Player: {Username}, Score: {Score}
// Total Players: {TotalPlayers}
}
}
}
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
1Các khái niệm cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiKhông gian tên và chỉ thịGiới thiệu về lớp và đối tượngTừ khóa thisPhương thức và tham sốTrường và thuộc tínhHàm khởi tạoKhởi tạo đối tượngÔn tập: Máy tính đơn giản4Kế thừa
Cú pháp kế thừa cơ bản (:)Từ khóa 'base'Từ khóa virtual và overrideLớp sealedLớp cơ sở 'object'Ôn tập: hệ phân cấp nhân viên7Tính năng nâng cao
Nạp chồng toán tửBộ lập chỉ mục (this[])Ghi đè ToString()Phương thức mở rộngÔn tập: Danh sách tùy chỉnh10Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếSingleton an toàn với luồngMẫu FactoryMẫu Observer (sự kiện)Mẫu Strategy2Thuộc tính và thành viên tĩnh
Thuộc tính tự độngThuộc tính chỉ đọc hoặc chỉ ghiTrường và phương thức tĩnhLớp tĩnhThành viên có thân biểu thức5Đa hình và interface
Đa hình lúc biên dịch và lúc chạyInterface và lớp trừu tượngNhiều interfaceInterface tường minhUpcasting và downcastingÔn tập: bộ tính toán hình học8Các khái niệm OOP nâng cao
Ưu tiên composition hơn kế thừaGenerics (lớp và phương thức)Delegate và sự kiệnAttribute và reflectionGiao diện IDisposable và câu lệnh usingKiến thức cơ bản về dependency injection11Các mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổ hợp3Kiến trúc lớp
Dữ liệu instance và dữ liệu tĩnhTừ khóa 'readonly' và 'const'Trường lưu trữÔn tập: Trình quản lý tài khoản ngân hàngTự luyện tập: Trình biên dịch C# online