MỤC TIÊU BÀI HỌC
Sau khi hoàn thành bài tập này, bạn sẽ:
✅ Xây dựng lớp
TaiKhoanNganHangmô phỏng tài khoản ngân hàng✅ Thực hành đóng gói dữ liệu với
privatefields✅ Sử dụng kiểu
decimalcho số dư tài khoản✅ Xây dựng các phương thức: nạp tiền, rút tiền, đổi mật khẩu
✅ Thực hành validation khi giao dịch
✅ Sử dụng static để đếm số tài khoản
┌─────────────────────────────────────────────────────────────┐
│ LỚP TAIKHOANNANGHANG │
├─────────────────────────────────────────────────────────────┤
│ │
│ 📦 FIELDS (Trường dữ liệu – Private) │
│ ├── _soTK : string (Số tài khoản – tự sinh) │
│ ├── _chuTK : string (Tên chủ tài khoản) │
│ ├── _soDu : decimal (Số dư) │
│ ├── _matKhau : string (Mật khẩu) │
│ └── _soLuongTK : static int (Đếm số TK đã tạo) │
│ │
│ 🔐 PROPERTIES (Thuộc tính) │
│ ├── SoTK { get; } (Read-only – tự sinh) │
│ ├── ChuTK { get; set; } (Có validation) │
│ └── SoDu { get; } (Read-only – chỉ xem) │
│ │
│ 🏗️ CONSTRUCTORS │
│ ├── TaiKhoanNganHang() (Mặc định – tự sinh số TK) │
│ └── TaiKhoanNganHang(chu, mk, du) (Có tham số) │
│ │
│ 🛠️ METHODS │
│ ├── HienThi() (Hiển thị thông tin) │
│ ├── NapTien(soTien) (Nạp tiền vào TK) │
│ ├── RutTien(soTien, mk) (Rút tiền – cần mật khẩu) │
│ └── DoiMatKhau(mkCu, mkMoi) (Đổi mật khẩu) │
│ │
└─────────────────────────────────────────────────────────────┘
BƯỚC 1: TẠO PROJECT MỚI
1.1. Mở Visual Studio
Mở Visual Studio 2022
1.2. Tạo Project mới
File → New → Project
Hoặc nhấn: Ctrl + Shift + N
1.3. Chọn loại Project
Gõ “Console” vào ô tìm kiếm
Chọn Console App (.NET Core) hoặc Console App (.NET Framework)
Nhấn Next
1.4. Đặt tên Project
Project name: Bai3_TaiKhoan Location: D:\CSharp\LapTrinhHuongDoiTuong (hoặc thư mục của bạn) Solution: LapTrinhHuongDoiTuong (chọn Add to Solution)
Nhấn Next
1.5. Chọn Framework
Chọn .NET 6.0 hoặc .NET 8.0 (LTS)
Nhấn Create
BƯỚC 2: TẠO CẤU TRÚC THƯ MỤC
2.1. Tạo thư mục Models
Trong Solution Explorer, click chuột phải vào Project
Bai3_TaiKhoanChọn Add → New Folder
Đặt tên:
ModelsNhấn Enter
BƯỚC 3: TẠO FILE LỚP TAIKHOANNANGHANG
3.1. Tạo file TaiKhoanNganHang.cs
Click chuột phải vào thư mục Models
Chọn Add → Class
Đặt tên:
TaiKhoanNganHang.csNhấn Add
BƯỚC 4: VIẾT CODE CHO LỚP TAIKHOANNANGHANG
4.1. Khai báo Namespace và Class
Mở file TaiKhoanNganHang.cs và viết:
using System; namespace Bai3_TaiKhoan.Models { public class TaiKhoanNganHang { // Code sẽ viết ở đây } }
4.2. Khai báo Fields (Trường dữ liệu)
public class TaiKhoanNganHang { // === FIELDS (Trường dữ liệu) === private string _soTK; // Số tài khoản (tự sinh) private string _chuTK; // Tên chủ tài khoản private decimal _soDu; // Số dư (dùng decimal cho tiền tệ) private string _matKhau; // Mật khẩu private static int _soLuongTK = 0; // Đếm số TK đã tạo (static) }
Giải thích Fields:
| Field | Kiểu | Mục đích | Lưu ý |
|---|---|---|---|
_soTK | string | Số tài khoản | Tự sinh, không thay đổi |
_chuTK | string | Tên chủ tài khoản | Kiểm tra không rỗng |
_soDu | decimal | Số dư | Dùng decimal cho tiền tệ |
_matKhau | string | Mật khẩu | Bảo vệ giao dịch |
_soLuongTK | static int | Đếm số TK đã tạo | Dùng chung |
4.3. Khai báo Properties (Thuộc tính)
a. Property SoTK (Read-only – chỉ đọc)
public class TaiKhoanNganHang { // ... Fields ở trên ... // === PROPERTIES === // 1. Số tài khoản - Chỉ đọc, tự sinh public string SoTK { get { return _soTK; } // Không có set → Không thể thay đổi từ bên ngoài } }
b. Property ChuTK (Có validation)
// 2. Tên chủ tài khoản - Có kiểm tra không rỗng public string ChuTK { get { return _chuTK; } set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Tên chủ tài khoản không được để trống!"); _chuTK = value.Trim(); } }
c. Property SoDu (Read-only)
// 3. Số dư - Chỉ đọc (không cho set trực tiếp) public decimal SoDu { get { return _soDu; } // Không có set → Chỉ thay đổi qua NapTien/RutTien }
4.4. Khai báo Constructors (Phương thức khởi tạo)
a. Constructor mặc định (Tự sinh số TK)
public class TaiKhoanNganHang { // ... Fields và Properties ở trên ... // === CONSTRUCTORS === // Constructor 1: Không tham số - Tự sinh số TK public TaiKhoanNganHang() { // Tăng số lượng TK lên 1 _soLuongTK++; // Tự sinh số TK: TK001, TK002, TK003, ... _soTK = "TK" + _soLuongTK.ToString("D3"); // Gán giá trị mặc định _chuTK = "Chưa xác định"; _matKhau = "123456"; // Mật khẩu mặc định _soDu = 0; } }
b. Constructor có tham số
// Constructor 2: Có tham số public TaiKhoanNganHang(string chuTK, string matKhau, decimal soDu = 0) : this() { // this() gọi constructor mặc định để tự sinh số TK // Gán giá trị (có validation) ChuTK = chuTK; _matKhau = matKhau; _soDu = soDu >= 0 ? soDu : 0; // Nếu số dư âm thì đặt về 0 }
Giải thích:
: this()– Gọi constructor mặc định trước (để tự sinh số TK)soDu = 0– Tham số tùy chọn, mặc định là 0Kiểm tra số dư không âm
4.5. Khai báo Methods (Phương thức)
a. Phương thức HienThi()
public class TaiKhoanNganHang { // ... Fields, Properties, Constructors ở trên ... // === METHODS === // 1. Hiển thị thông tin tài khoản public void HienThi() { Console.WriteLine("═══════════════════════════════════════"); Console.WriteLine($" Số TK : {_soTK}"); Console.WriteLine($" Chủ TK : {_chuTK}"); Console.WriteLine($" Số dư : {_soDu:N0} VND"); Console.WriteLine("═══════════════════════════════════════"); } }
b. Phương thức NapTien() – Nạp tiền
// 2. Nạp tiền vào tài khoản public bool NapTien(decimal soTien) { // Kiểm tra số tiền nạp phải > 0 if (soTien <= 0) { Console.WriteLine("❌ Số tiền nạp phải lớn hơn 0!"); return false; } // Cộng thêm vào số dư _soDu += soTien; Console.WriteLine($"✓ Đã nạp {soTien:N0} VND. Số dư: {_soDu:N0} VND"); return true; }
c. Phương thức RutTien() – Rút tiền
// 3. Rút tiền từ tài khoản (cần mật khẩu) public bool RutTien(decimal soTien, string matKhau) { // Kiểm tra mật khẩu if (matKhau != _matKhau) { Console.WriteLine("❌ Mật khẩu sai!"); return false; } // Kiểm tra số tiền rút phải > 0 if (soTien <= 0) { Console.WriteLine("❌ Số tiền rút phải lớn hơn 0!"); return false; } // Kiểm tra số dư có đủ không if (soTien > _soDu) { Console.WriteLine($"❌ Số dư không đủ! (Số dư: {_soDu:N0} VND)"); return false; } // Trừ vào số dư _soDu -= soTien; Console.WriteLine($"✓ Đã rút {soTien:N0} VND. Số dư: {_soDu:N0} VND"); return true; }
d. Phương thức DoiMatKhau() – Đổi mật khẩu
// 4. Đổi mật khẩu public bool DoiMatKhau(string matKhauCu, string matKhauMoi) { // Kiểm tra mật khẩu cũ if (matKhauCu != _matKhau) { Console.WriteLine("❌ Mật khẩu cũ sai!"); return false; } // Kiểm tra mật khẩu mới không được rỗng if (string.IsNullOrWhiteSpace(matKhauMoi)) { Console.WriteLine("❌ Mật khẩu mới không được để trống!"); return false; } // Kiểm tra mật khẩu mới tối thiểu 6 ký tự if (matKhauMoi.Length < 6) { Console.WriteLine("❌ Mật khẩu mới phải có ít nhất 6 ký tự!"); return false; } // Đổi mật khẩu _matKhau = matKhauMoi; Console.WriteLine("✓ Đổi mật khẩu thành công!"); return true; }
4.6. Code hoàn chỉnh của TaiKhoanNganHang.cs
using System; namespace Bai3_TaiKhoan.Models { public class TaiKhoanNganHang { // === FIELDS === private string _soTK; private string _chuTK; private decimal _soDu; private string _matKhau; private static int _soLuongTK = 0; // === PROPERTIES === // 1. Số tài khoản - Read-only public string SoTK => _soTK; // 2. Tên chủ tài khoản - Có validation public string ChuTK { get => _chuTK; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Tên chủ tài khoản không được để trống!"); _chuTK = value.Trim(); } } // 3. Số dư - Read-only public decimal SoDu => _soDu; // === CONSTRUCTORS === // Constructor mặc định - Tự sinh số TK public TaiKhoanNganHang() { _soLuongTK++; _soTK = "TK" + _soLuongTK.ToString("D3"); _chuTK = "Chưa xác định"; _matKhau = "123456"; _soDu = 0; } // Constructor có tham số public TaiKhoanNganHang(string chuTK, string matKhau, decimal soDu = 0) : this() { ChuTK = chuTK; _matKhau = matKhau; _soDu = soDu >= 0 ? soDu : 0; } // === METHODS === // 1. Hiển thị thông tin public void HienThi() { Console.WriteLine("═══════════════════════════════════════"); Console.WriteLine($" Số TK : {_soTK}"); Console.WriteLine($" Chủ TK : {_chuTK}"); Console.WriteLine($" Số dư : {_soDu:N0} VND"); Console.WriteLine("═══════════════════════════════════════"); } // 2. Nạp tiền public bool NapTien(decimal soTien) { if (soTien <= 0) { Console.WriteLine("❌ Số tiền nạp phải lớn hơn 0!"); return false; } _soDu += soTien; Console.WriteLine($"✓ Đã nạp {soTien:N0} VND. Số dư: {_soDu:N0} VND"); return true; } // 3. Rút tiền public bool RutTien(decimal soTien, string matKhau) { if (matKhau != _matKhau) { Console.WriteLine("❌ Mật khẩu sai!"); return false; } if (soTien <= 0) { Console.WriteLine("❌ Số tiền rút phải lớn hơn 0!"); return false; } if (soTien > _soDu) { Console.WriteLine($"❌ Số dư không đủ! (Số dư: {_soDu:N0} VND)"); return false; } _soDu -= soTien; Console.WriteLine($"✓ Đã rút {soTien:N0} VND. Số dư: {_soDu:N0} VND"); return true; } // 4. Đổi mật khẩu public bool DoiMatKhau(string matKhauCu, string matKhauMoi) { if (matKhauCu != _matKhau) { Console.WriteLine("❌ Mật khẩu cũ sai!"); return false; } if (string.IsNullOrWhiteSpace(matKhauMoi)) { Console.WriteLine("❌ Mật khẩu mới không được để trống!"); return false; } if (matKhauMoi.Length < 6) { Console.WriteLine("❌ Mật khẩu mới phải có ít nhất 6 ký tự!"); return false; } _matKhau = matKhauMoi; Console.WriteLine("✓ Đổi mật khẩu thành công!"); return true; } } }
BƯỚC 5: VIẾT CHƯƠNG TRÌNH KIỂM TRA (TEST)
5.1. Mở file Program.cs
Trong Solution Explorer, mở file Program.cs của Project Bai3_TaiKhoan.
5.2. Viết code test
using System; using Bai3_TaiKhoan.Models; namespace Bai3_TaiKhoan { class Program { static void Main(string[] args) { Console.OutputEncoding = System.Text.Encoding.UTF8; Console.WriteLine("===== BÀI TẬP 3: LỚP TÀI KHOẢN NGÂN HÀNG =====\n"); // ============================================ // TEST 1: Constructor mặc định // ============================================ Console.WriteLine("1. Constructor mặc định:"); TaiKhoanNganHang tk1 = new TaiKhoanNganHang(); tk1.HienThi(); // ============================================ // TEST 2: Constructor có tham số // ============================================ Console.WriteLine("\n2. Constructor có tham số:"); TaiKhoanNganHang tk2 = new TaiKhoanNganHang( "Nguyễn Văn A", "123456", 1000000 ); tk2.HienThi(); // ============================================ // TEST 3: Tạo thêm tài khoản (xem tự sinh số TK) // ============================================ Console.WriteLine("\n3. Tạo thêm tài khoản:"); TaiKhoanNganHang tk3 = new TaiKhoanNganHang("Trần Thị B", "abc123", 500000); TaiKhoanNganHang tk4 = new TaiKhoanNganHang("Lê Văn C", "xyz789"); Console.WriteLine($" Số TK3: {tk3.SoTK} - Chủ TK: {tk3.ChuTK}"); Console.WriteLine($" Số TK4: {tk4.SoTK} - Chủ TK: {tk4.ChuTK}"); // ============================================ // TEST 4: Nạp tiền // ============================================ Console.WriteLine("\n4. Nạp tiền:"); tk2.NapTien(500000); tk2.HienThi(); // ============================================ // TEST 5: Rút tiền (đúng mật khẩu) // ============================================ Console.WriteLine("\n5. Rút tiền (đúng mật khẩu):"); tk2.RutTien(300000, "123456"); tk2.HienThi(); // ============================================ // TEST 6: Rút tiền (sai mật khẩu) // ============================================ Console.WriteLine("\n6. Rút tiền (sai mật khẩu):"); tk2.RutTien(100000, "sai_mat_khau"); // ============================================ // TEST 7: Rút tiền (vượt số dư) // ============================================ Console.WriteLine("\n7. Rút tiền (vượt số dư):"); tk2.RutTien(2000000, "123456"); // ============================================ // TEST 8: Rút tiền (số tiền <= 0) // ============================================ Console.WriteLine("\n8. Rút tiền (số tiền <= 0):"); tk2.RutTien(-50000, "123456"); // ============================================ // TEST 9: Đổi mật khẩu (đúng) // ============================================ Console.WriteLine("\n9. Đổi mật khẩu (đúng):"); tk2.DoiMatKhau("123456", "newpass123"); // ============================================ // TEST 10: Đổi mật khẩu (sai mật khẩu cũ) // ============================================ Console.WriteLine("\n10. Đổi mật khẩu (sai mật khẩu cũ):"); tk2.DoiMatKhau("wrong_old", "newpass456"); // ============================================ // TEST 11: Đổi mật khẩu (quá ngắn) // ============================================ Console.WriteLine("\n11. Đổi mật khẩu (quá ngắn):"); tk2.DoiMatKhau("newpass123", "123"); // ============================================ // TEST 12: Thông tin cuối cùng // ============================================ Console.WriteLine("\n12. Thông tin cuối cùng của TK2:"); tk2.HienThi(); Console.WriteLine("\nNhấn phím bất kỳ để thoát..."); Console.ReadKey(); } } }
BƯỚC 6: CHẠY CHƯƠNG TRÌNH
6.1. Build Project
Nhấn
Ctrl + Shift + Bđể biên dịch
6.2. Chạy chương trình
Nhấn
F5để chạy (Debug mode)Hoặc
Ctrl + F5để chạy không debug
KẾT QUẢ DỰ KIẾN
===== BÀI TẬP 3: LỚP TÀI KHOẢN NGÂN HÀNG ===== 1. Constructor mặc định: ═══════════════════════════════════════ Số TK : TK001 Chủ TK : Chưa xác định Số dư : 0 VND ═══════════════════════════════════════ 2. Constructor có tham số: ═══════════════════════════════════════ Số TK : TK002 Chủ TK : Nguyễn Văn A Số dư : 1,000,000 VND ═══════════════════════════════════════ 3. Tạo thêm tài khoản: Số TK3: TK003 - Chủ TK: Trần Thị B Số TK4: TK004 - Chủ TK: Lê Văn C 4. Nạp tiền: ✓ Đã nạp 500,000 VND. Số dư: 1,500,000 VND ═══════════════════════════════════════ Số TK : TK002 Chủ TK : Nguyễn Văn A Số dư : 1,500,000 VND ═══════════════════════════════════════ 5. Rút tiền (đúng mật khẩu): ✓ Đã rút 300,000 VND. Số dư: 1,200,000 VND ═══════════════════════════════════════ Số TK : TK002 Chủ TK : Nguyễn Văn A Số dư : 1,200,000 VND ═══════════════════════════════════════ 6. Rút tiền (sai mật khẩu): ❌ Mật khẩu sai! 7. Rút tiền (vượt số dư): ❌ Số dư không đủ! (Số dư: 1,200,000 VND) 8. Rút tiền (số tiền <= 0): ❌ Số tiền rút phải lớn hơn 0! 9. Đổi mật khẩu (đúng): ✓ Đổi mật khẩu thành công! 10. Đổi mật khẩu (sai mật khẩu cũ): ❌ Mật khẩu cũ sai! 11. Đổi mật khẩu (quá ngắn): ❌ Mật khẩu mới phải có ít nhất 6 ký tự! 12. Thông tin cuối cùng của TK2: ═══════════════════════════════════════ Số TK : TK002 Chủ TK : Nguyễn Văn A Số dư : 1,200,000 VND ═══════════════════════════════════════ Nhấn phím bất kỳ để thoát...