Cấu trúc
NhanVien (Abstract)
├── NhanVienVanPhong
│ └── TinhLuong() = LuongCoBan + SoNgayLam * 200000
├── NhanVienSanXuat
│ └── TinhLuong() = LuongCoBan + SoSanPham * 50000
└── NhanVienQuanLy
└── TinhLuong() = LuongCoBan * 2 + Thuong CẤU TRÚC PROJECT
Bai1_NhanVien (Project) ├── Models/ │ ├── NhanVien.cs ← Lớp cha trừu tượng │ ├── NhanVienVanPhong.cs ← Lớp con 1 │ ├── NhanVienSanXuat.cs ← Lớp con 2 │ └── NhanVienQuanLy.cs ← Lớp con 3 └── Program.cs ← Chạy test
BƯỚC 1: TẠO PROJECT MỚI
BƯỚC 2: TẠO CẤU TRÚC THƯ MỤC
BƯỚC 3: VIẾT CODE CÁC LỚP
BƯỚC 4: VIẾT CHƯƠNG TRÌNH TEST (Program.cs)
1. Tạo file NhanVien.cs (Lớp cha trừu tượng)
using System; namespace Bai1_NhanVien.Models { /// <summary> /// Lớp trừu tượng NhanVien - Làm lớp nền cho các lớp con /// abstract: Không thể tạo đối tượng từ lớp này /// </summary> public abstract class NhanVien { // === FIELDS (Trường dữ liệu) === private string _maNV; // Mã nhân viên private string _hoTen; // Họ tên private DateTime _ngaySinh; // Ngày sinh private double _luongCoBan; // Lương cơ bản // === PROPERTIES (Thuộc tính) === /// <summary> /// Mã nhân viên - Không được để trống /// </summary> public string MaNV { get { return _maNV; } set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Mã NV không được để trống!"); _maNV = value.Trim(); } } /// <summary> /// Họ tên - Không được để trống /// </summary> public string HoTen { get { return _hoTen; } set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Họ tên không được để trống!"); _hoTen = value.Trim(); } } /// <summary> /// Ngày sinh - Hợp lệ, không trong tương lai /// </summary> public DateTime NgaySinh { get { return _ngaySinh; } set { if (value > DateTime.Now) throw new ArgumentException("Ngày sinh không được trong tương lai!"); if (value < new DateTime(1900, 1, 1)) throw new ArgumentException("Ngày sinh không hợp lệ!"); _ngaySinh = value; } } /// <summary> /// Lương cơ bản - Không được âm /// </summary> public double LuongCoBan { get { return _luongCoBan; } set { if (value < 0) throw new ArgumentException("Lương cơ bản không được âm!"); _luongCoBan = value; } } // === COMPUTED PROPERTIES (Tính toán tự động) === /// <summary> /// Tuổi - Tự động tính từ ngày sinh /// </summary> public int Tuoi { get { DateTime today = DateTime.Today; int age = today.Year - _ngaySinh.Year; if (_ngaySinh.Date > today.AddYears(-age)) age--; return age; } } // === CONSTRUCTORS === /// <summary> /// Constructor mặc định /// </summary> public NhanVien() { _maNV = "NV001"; _hoTen = "Chưa xác định"; _ngaySinh = new DateTime(2000, 1, 1); _luongCoBan = 0; } /// <summary> /// Constructor có tham số /// </summary> public NhanVien(string ma, string ten, DateTime ngaySinh, double luong) { MaNV = ma; HoTen = ten; NgaySinh = ngaySinh; LuongCoBan = luong; } // === ABSTRACT METHOD - BẮT BUỘC LỚP CON TRIỂN KHAI === /// <summary> /// Phương thức trừu tượng TinhLuong() /// Lớp con BẮT BUỘC phải override (ghi đè) phương thức này /// </summary> public abstract double TinhLuong(); // === VIRTUAL METHOD - CÓ THỂ GHI ĐÈ === /// <summary> /// Hiển thị thông tin nhân viên /// virtual: Cho phép lớp con ghi đè (override) /// </summary> public virtual void HienThi() { Console.WriteLine("═══════════════════════════════════════"); Console.WriteLine($" Mã NV : {_maNV}"); Console.WriteLine($" Họ tên : {_hoTen}"); Console.WriteLine($" Ngày sinh : {_ngaySinh:dd/MM/yyyy}"); Console.WriteLine($" Tuổi : {Tuoi}"); Console.WriteLine($" Lương CB : {_luongCoBan:N0} VND"); Console.WriteLine($" Lương TT : {TinhLuong():N0} VND"); Console.WriteLine("═══════════════════════════════════════"); } } }
2. Tạo file NhanVienVanPhong.cs (Lớp con 1)
csharp
using System; namespace Bai1_NhanVien.Models { /// <summary> /// Lớp NhanVienVanPhong kế thừa từ NhanVien /// </summary> public class NhanVienVanPhong : NhanVien // : NhanVien = kế thừa { // === FIELD RIÊNG === private int _soNgayLamViec; // Số ngày làm việc trong tháng // === PROPERTY RIÊNG === public int SoNgayLamViec { get { return _soNgayLamViec; } set { if (value < 0 || value > 31) throw new ArgumentException("Số ngày làm việc phải từ 0 đến 31!"); _soNgayLamViec = value; } } // === CONSTRUCTORS === /// <summary> /// Constructor mặc định /// : base() gọi constructor của NhanVien /// </summary> public NhanVienVanPhong() : base() { _soNgayLamViec = 0; } /// <summary> /// Constructor có tham số /// : base(ma, ten, ngaySinh, luong) gọi constructor của NhanVien /// </summary> public NhanVienVanPhong(string ma, string ten, DateTime ngaySinh, double luong, int soNgay) : base(ma, ten, ngaySinh, luong) { SoNgayLamViec = soNgay; } // === GHI ĐÈ PHƯƠNG THỨC TRỪU TƯỢNG === /// <summary> /// Tính lương cho nhân viên văn phòng /// Lương = Lương cơ bản + (Số ngày làm việc × 200,000) /// override: Ghi đè phương thức abstract của lớp cha /// </summary> public override double TinhLuong() { return LuongCoBan + (_soNgayLamViec * 200000); } // === GHI ĐÈ PHƯƠNG THỨC HIỂN THỊ === /// <summary> /// Hiển thị thông tin nhân viên văn phòng /// override: Ghi đè phương thức HienThi() của lớp cha /// </summary> public override void HienThi() { // Gọi phương thức của lớp cha để hiển thị thông tin cơ bản base.HienThi(); // Thêm thông tin riêng Console.WriteLine($" Loại : Nhân viên văn phòng"); Console.WriteLine($" Số ngày làm: {_soNgayLamViec}"); Console.WriteLine("═══════════════════════════════════════"); } } }
3. Tạo file NhanVienSanXuat.cs (Lớp con 2)
using System; namespace Bai1_NhanVien.Models { /// <summary> /// Lớp NhanVienSanXuat kế thừa từ NhanVien /// </summary> public class NhanVienSanXuat : NhanVien { // === FIELD RIÊNG === private int _soSanPham; // Số sản phẩm làm được private double _donGiaSanPham; // Đơn giá mỗi sản phẩm // === PROPERTIES RIÊNG === public int SoSanPham { get { return _soSanPham; } set { if (value < 0) throw new ArgumentException("Số sản phẩm không được âm!"); _soSanPham = value; } } public double DonGiaSanPham { get { return _donGiaSanPham; } set { if (value < 0) throw new ArgumentException("Đơn giá sản phẩm không được âm!"); _donGiaSanPham = value; } } // === CONSTRUCTORS === public NhanVienSanXuat() : base() { _soSanPham = 0; _donGiaSanPham = 50000; // Mặc định 50,000 VND/sản phẩm } public NhanVienSanXuat(string ma, string ten, DateTime ngaySinh, double luong, int soSanPham, double donGia = 50000) : base(ma, ten, ngaySinh, luong) { SoSanPham = soSanPham; DonGiaSanPham = donGia; } // === GHI ĐÈ === /// <summary> /// Tính lương nhân viên sản xuất /// Lương = Lương cơ bản + (Số sản phẩm × Đơn giá) /// </summary> public override double TinhLuong() { return LuongCoBan + (_soSanPham * _donGiaSanPham); } public override void HienThi() { base.HienThi(); Console.WriteLine($" Loại : Nhân viên sản xuất"); Console.WriteLine($" Số SP : {_soSanPham}"); Console.WriteLine($" Đơn giá SP : {_donGiaSanPham:N0} VND"); Console.WriteLine("═══════════════════════════════════════"); } } }
4. Tạo file NhanVienQuanLy.cs (Lớp con 3)
using System; namespace Bai1_NhanVien.Models { /// <summary> /// Lớp NhanVienQuanLy kế thừa từ NhanVien /// </summary> public class NhanVienQuanLy : NhanVien { // === FIELD RIÊNG === private double _thuong; // Tiền thưởng private int _soNhanVienQuanLy; // Số nhân viên quản lý // === PROPERTIES RIÊNG === public double Thuong { get { return _thuong; } set { if (value < 0) throw new ArgumentException("Thưởng không được âm!"); _thuong = value; } } public int SoNhanVienQuanLy { get { return _soNhanVienQuanLy; } set { if (value < 0) throw new ArgumentException("Số nhân viên quản lý không được âm!"); _soNhanVienQuanLy = value; } } // === CONSTRUCTORS === public NhanVienQuanLy() : base() { _thuong = 0; _soNhanVienQuanLy = 0; } public NhanVienQuanLy(string ma, string ten, DateTime ngaySinh, double luong, double thuong, int soNhanVien) : base(ma, ten, ngaySinh, luong) { Thuong = thuong; SoNhanVienQuanLy = soNhanVien; } // === GHI ĐÈ === /// <summary> /// Tính lương nhân viên quản lý /// Lương = Lương cơ bản × 2 + Thưởng /// </summary> public override double TinhLuong() { return LuongCoBan * 2 + _thuong; } public override void HienThi() { base.HienThi(); Console.WriteLine($" Loại : Nhân viên quản lý"); Console.WriteLine($" Thưởng : {_thuong:N0} VND"); Console.WriteLine($" Số NV QL : {_soNhanVienQuanLy}"); Console.WriteLine("═══════════════════════════════════════"); } } }
Program.cs
using System; using System.Collections.Generic; using Bai1_NhanVien.Models; namespace Bai1_NhanVien { class Program { static void Main(string[] args) { Console.OutputEncoding = System.Text.Encoding.UTF8; Console.WriteLine("═══════════════════════════════════════════════════"); Console.WriteLine(" BÀI TẬP 1: XÂY DỰNG CÁC LỚP NHÂN VIÊN"); Console.WriteLine("═══════════════════════════════════════════════════\n"); // ================================================================ // PHẦN 1: TẠO DANH SÁCH NHÂN VIÊN (ĐA HÌNH) // ================================================================ /// <summary> /// List<NhanVien> có thể chứa cả 3 loại nhân viên /// Đây là tính đa hình (Polymorphism) /// </summary> List<NhanVien> danhSachNV = new List<NhanVien>(); // Tạo nhân viên văn phòng danhSachNV.Add(new NhanVienVanPhong( "NV001", "Nguyễn Văn A", new DateTime(1990, 5, 10), 8000000, 22 )); // Tạo nhân viên sản xuất danhSachNV.Add(new NhanVienSanXuat( "NV002", "Trần Thị B", new DateTime(1995, 8, 15), 6000000, 150 )); // Tạo nhân viên quản lý danhSachNV.Add(new NhanVienQuanLy( "NV003", "Lê Văn C", new DateTime(1985, 12, 20), 12000000, 5000000, 10 )); // ================================================================ // PHẦN 2: HIỂN THỊ DANH SÁCH // ================================================================ Console.WriteLine("▶ DANH SÁCH NHÂN VIÊN:"); Console.WriteLine("───────────────────────────────────────────────────\n"); /// <summary> /// Duyệt qua danh sách và gọi HienThi() /// Mỗi nhân viên tự biết cách hiển thị của mình /// </summary> foreach (NhanVien nv in danhSachNV) { nv.HienThi(); // Gọi HienThi() đã được override Console.WriteLine(); } // ================================================================ // PHẦN 3: THỐNG KÊ // ================================================================ Console.WriteLine("▶ THỐNG KÊ NHÂN VIÊN:"); Console.WriteLine("───────────────────────────────────────────────────\n"); /// <summary> /// Tính tổng lương công ty /// </summary> double tongLuong = 0; foreach (NhanVien nv in danhSachNV) { tongLuong += nv.TinhLuong(); } Console.WriteLine($" Tổng lương công ty: {tongLuong:N0} VND"); /// <summary> /// Tìm lương cao nhất /// </summary> double luongCaoNhat = 0; NhanVien nvCaoNhat = null; foreach (NhanVien nv in danhSachNV) { if (nv.TinhLuong() > luongCaoNhat) { luongCaoNhat = nv.TinhLuong(); nvCaoNhat = nv; } } if (nvCaoNhat != null) { Console.WriteLine($" Nhân viên lương cao nhất: {nvCaoNhat.HoTen}"); Console.WriteLine($" Lương: {luongCaoNhat:N0} VND"); } /// <summary> /// Đếm số nhân viên theo loại /// </summary> int nvVP = 0, nvSX = 0, nvQL = 0; foreach (NhanVien nv in danhSachNV) { if (nv is NhanVienVanPhong) nvVP++; else if (nv is NhanVienSanXuat) nvSX++; else if (nv is NhanVienQuanLy) nvQL++; } Console.WriteLine($"\n Nhân viên văn phòng: {nvVP}"); Console.WriteLine($" Nhân viên sản xuất : {nvSX}"); Console.WriteLine($" Nhân viên quản lý : {nvQL}"); // ================================================================ // PHẦN 4: THỬ NHẬP TỪ BÀN PHÍM // ================================================================ Console.WriteLine("\n▶ THỬ NHẬP NHÂN VIÊN MỚI:"); Console.WriteLine("───────────────────────────────────────────────────\n"); try { Console.Write(" Mã NV: "); string ma = Console.ReadLine(); Console.Write(" Họ tên: "); string ten = Console.ReadLine(); Console.Write(" Ngày sinh (dd/MM/yyyy): "); DateTime ngaySinh = DateTime.ParseExact(Console.ReadLine(), "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture); Console.Write(" Lương cơ bản: "); double luong = double.Parse(Console.ReadLine()); Console.Write(" Loại nhân viên (1: VP, 2: SX, 3: QL): "); int loai = int.Parse(Console.ReadLine()); NhanVien nvMoi = null; switch (loai) { case 1: // Văn phòng Console.Write(" Số ngày làm việc: "); int ngay = int.Parse(Console.ReadLine()); nvMoi = new NhanVienVanPhong(ma, ten, ngaySinh, luong, ngay); break; case 2: // Sản xuất Console.Write(" Số sản phẩm: "); int sp = int.Parse(Console.ReadLine()); Console.Write(" Đơn giá sản phẩm (mặc định 50000): "); string donGiaStr = Console.ReadLine(); double donGia = string.IsNullOrEmpty(donGiaStr) ? 50000 : double.Parse(donGiaStr); nvMoi = new NhanVienSanXuat(ma, ten, ngaySinh, luong, sp, donGia); break; case 3: // Quản lý Console.Write(" Thưởng: "); double thuong = double.Parse(Console.ReadLine()); Console.Write(" Số nhân viên quản lý: "); int soNV = int.Parse(Console.ReadLine()); nvMoi = new NhanVienQuanLy(ma, ten, ngaySinh, luong, thuong, soNV); break; default: Console.WriteLine(" ❌ Loại nhân viên không hợp lệ!"); break; } if (nvMoi != null) { danhSachNV.Add(nvMoi); Console.WriteLine("\n ✅ Đã thêm nhân viên mới thành công!"); nvMoi.HienThi(); } } catch (Exception ex) { Console.WriteLine($" ❌ Lỗi: {ex.Message}"); } Console.WriteLine("\n═══════════════════════════════════════════════════"); Console.WriteLine("NHẤN PHÍM BẤT KỲ ĐỂ THOÁT..."); Console.ReadKey(); } } }
KẾT QUẢ DỰ KIẾN
text
═══════════════════════════════════════════════════
BÀI TẬP 1: XÂY DỰNG CÁC LỚP NHÂN VIÊN
═══════════════════════════════════════════════════
▶ DANH SÁCH NHÂN VIÊN:
───────────────────────────────────────────────────
═══════════════════════════════════════
Mã NV : NV001
Họ tên : Nguyễn Văn A
Ngày sinh : 10/05/1990
Tuổi : 34
Lương CB : 8,000,000 VND
Lương TT : 12,400,000 VND
Loại : Nhân viên văn phòng
Số ngày làm: 22
═══════════════════════════════════════
═══════════════════════════════════════
Mã NV : NV002
Họ tên : Trần Thị B
Ngày sinh : 15/08/1995
Tuổi : 29
Lương CB : 6,000,000 VND
Lương TT : 13,500,000 VND
Loại : Nhân viên sản xuất
Số SP : 150
Đơn giá SP : 50,000 VND
═══════════════════════════════════════
═══════════════════════════════════════
Mã NV : NV003
Họ tên : Lê Văn C
Ngày sinh : 20/12/1985
Tuổi : 39
Lương CB : 12,000,000 VND
Lương TT : 29,000,000 VND
Loại : Nhân viên quản lý
Thưởng : 5,000,000 VND
Số NV QL : 10
═══════════════════════════════════════
▶ THỐNG KÊ NHÂN VIÊN:
───────────────────────────────────────────────────
Tổng lương công ty: 54,900,000 VND
Nhân viên lương cao nhất: Lê Văn C
Lương: 29,000,000 VND
Nhân viên văn phòng: 1
Nhân viên sản xuất : 1
Nhân viên quản lý : 1
▶ THỬ NHẬP NHÂN VIÊN MỚI:
───────────────────────────────────────────────────
Mã NV: NV004
Họ tên: Phạm Văn D
Ngày sinh (dd/MM/yyyy): 25/12/2000
Lương cơ bản: 7000000
Loại nhân viên (1: VP, 2: SX, 3: QL): 1
Số ngày làm việc: 20
✅ Đã thêm nhân viên mới thành công!
═══════════════════════════════════════
Mã NV : NV004
Họ tên : Phạm Văn D
Ngày sinh : 25/12/2000
Tuổi : 24
Lương CB : 7,000,000 VND
Lương TT : 11,000,000 VND
Loại : Nhân viên văn phòng
Số ngày làm: 20
═══════════════════════════════════════
═══════════════════════════════════════════════════
NHẤN PHÍM BẤT KỲ ĐỂ THOÁT...