BÀI 9: LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG TRONG C#

9.1. Tổng quan về Lập trình hướng đối tượng

Định nghĩa: Lập trình hướng đối tượng (OOP – Object-Oriented Programming) là phương pháp lập trình dựa trên mô hình các đối tượng trong thế giới thực, trong đó mỗi đối tượng có:

  • Trạng thái (State): Các thuộc tính, dữ liệu

  • Hành vi (Behavior): Các phương thức, chức năng

  • Định danh (Identity): Mỗi đối tượng có một danh tính riêng

4 tính chất cơ bản của OOP:

Tính chấtÝ nghĩa
Đóng gói (Encapsulation)Che giấu dữ liệu bên trong, chỉ cung cấp giao diện tương tác
Kế thừa (Inheritance)Lớp con kế thừa các đặc điểm từ lớp cha
Đa hình (Polymorphism)Cùng một hành động nhưng có cách thực hiện khác nhau
Trừu tượng (Abstraction)Chỉ hiển thị thông tin cần thiết, ẩn đi chi tiết phức tạp

9.1.2. Lớp (Class) và Đối tượng (Object) (0.3 giờ)

a. Khái niệm:

  • Lớp (Class): Khuôn mẫu (blueprint) để tạo ra các đối tượng

  • Đối tượng (Object): Thể hiện cụ thể của lớp (instance)

b. Cú pháp khai báo lớp:

[Access Modifier] class TênLớp
{
    // 1. Fields (Trường dữ liệu)
    // 2. Properties (Thuộc tính)
    // 3. Constructors (Phương thức khởi tạo)
    // 4. Methods (Phương thức)
    // 5. Events (Sự kiện)
}

c. Ví dụ cụ thể:

public class SinhVien
{
    // Fields
    private string _maSV;
    private string _hoTen;
    private int _namSinh;
    private double _diemTB;
    
    // Properties
    public string MaSV { get => _maSV; set => _maSV = value; }
    public string HoTen { get => _hoTen; set => _hoTen = value; }
    public int NamSinh { get => _namSinh; set => _namSinh = value; }
    public double DiemTB { get => _diemTB; set => _diemTB = value; }
    
    // Constructor
    public SinhVien() { }
    public SinhVien(string ma, string ten, int nam, double diem)
    {
        _maSV = ma;
        _hoTen = ten;
        _namSinh = nam;
        _diemTB = diem;
    }
    
    // Methods
    public void HienThi()
    {
        Console.WriteLine($"Mã SV: {_maSV}");
        Console.WriteLine($"Họ tên: {_hoTen}");
        Console.WriteLine($"Năm sinh: {_namSinh}");
        Console.WriteLine($"Điểm TB: {_diemTB:F2}");
    }
}

d. Tạo và sử dụng đối tượng:

// Tạo đối tượng
SinhVien sv1 = new SinhVien();                    // Dùng constructor mặc định
SinhVien sv2 = new SinhVien("SV001", "Nguyễn Văn A", 2005, 8.5); // Dùng constructor có tham số

// Truy cập thành viên
sv2.HoTen = "Nguyễn Văn B";
sv2.DiemTB = 9.0;
sv2.HienThi();

9.3. Phương thức khởi tạo (Constructor) (0.3 giờ)

a. Constructor mặc định (Default Constructor):

public class NhanVien
{
    public NhanVien()
    {
        // Khởi tạo giá trị mặc định
        MaNV = "NV001";
        HoTen = "Chưa xác định";
        LuongCoBan = 5000000;
    }
}

b. Constructor có tham số:

public class NhanVien
{
    public NhanVien(string ma, string ten, double luong)
    {
        MaNV = ma;
        HoTen = ten;
        LuongCoBan = luong;
    }
}

c. Constructor overloading (nạp chồng):

public class NhanVien
{
    // Constructor không tham số
    public NhanVien() { }
    
    // Constructor 1 tham số
    public NhanVien(string ma) : this(ma, "Chưa xác định", 5000000) { }
    
    // Constructor 2 tham số
    public NhanVien(string ma, string ten) : this(ma, ten, 5000000) { }
    
    // Constructor 3 tham số
    public NhanVien(string ma, string ten, double luong)
    {
        MaNV = ma;
        HoTen = ten;
        LuongCoBan = luong;
    }
}

d. Static Constructor (Constructor tĩnh):

public class Database
{
    public static string ConnectionString;
    
    // Static constructor - chạy 1 lần duy nhất khi class được load
    static Database()
    {
        ConnectionString = "Server=localhost;Database=MyDB;";
        Console.WriteLine("Database initialized");
    }
}

e. Private Constructor:

public class Utility
{
    // Private constructor - không thể tạo instance bên ngoài
    private Utility() { }
    
    // Chỉ chứa static members
    public static int Add(int a, int b) => a + b;
}

9.4. Từ khóa this và base 

a. Từ khóa this:

  • Tham chiếu đến đối tượng hiện tại

  • Phân biệt biến local và field cùng tên

  • Gọi constructor khác trong cùng class

csharp
public class SinhVien
{
    private string maSV;
    
    public string MaSV
    {
        get { return maSV; }
        set { maSV = value; }
    }
    
    public SinhVien(string maSV)  // Tham số trùng tên với field
    {
        this.maSV = maSV;         // this để phân biệt
    }
    
    public SinhVien() : this("SV001")  // Gọi constructor khác
    {
        // Code khởi tạo thêm
    }
}

b. Từ khóa base (sẽ học kỹ ở Bài 10):

  • Tham chiếu đến thành phần của lớp cha

  • Gọi constructor của lớp cha

  • Gọi phương thức của lớp cha

9.5. Thuộc tính (Properties) (0.4 giờ)

a. Auto-implemented Properties (C# 3.0+):

public class SinhVien
{
    public string MaSV { get; set; }
    public string HoTen { get; set; }
    public int NamSinh { get; set; }
    public double DiemTB { get; set; }
}

b. Properties với logic kiểm tra:

public class SinhVien
{
    private double _diemTB;
    
    public double DiemTB
    {
        get { return _diemTB; }
        set
        {
            if (value >= 0 && value <= 10)
                _diemTB = value;
            else
                throw new ArgumentException("Điểm phải từ 0 đến 10");
        }
    }
}

c. Read-only và Write-only Properties:

public class SinhVien
{
    private string _maSV;
    
    // Read-only - chỉ có get
    public string MaSV => _maSV;  // Hoặc { get; }
    
    // Write-only - chỉ có set (ít dùng)
    public string MatKhau { set { _matKhau = value; } }
    
    // Compute Property (tính toán)
    public int Tuoi => DateTime.Now.Year - NamSinh;
}

d. Expression-bodied Properties (C# 6+):

public class HinhTron
{
    public double BanKinh { get; set; }
    
    // Expression-bodied
    public double DienTich => Math.PI * BanKinh * BanKinh;
    public double ChuVi => 2 * Math.PI * BanKinh;
}

e. Properties với get/set khác access modifier:

public class SinhVien
{
    public string MaSV { get; private set; }  // Chỉ có thể set trong class
    public string HoTen { get; set; }
    public double DiemTB { get; private set; }
    
    public SinhVien(string ma)
    {
        MaSV = ma;  // OK - set trong class
    }
    // Không thể set MaSV từ bên ngoài
}

9.6. Phạm vi truy cập (Access Modifiers) (0.2 giờ)

ModifierMô tảVí dụ sử dụng
publicTruy cập từ mọi nơiAPI, interface công khai
privateChỉ trong cùng lớpFields, helper methods
protectedTrong lớp và lớp conDùng trong kế thừa
internalTrong cùng assemblyThư viện nội bộ
protected internalLớp con hoặc cùng assemblyKết hợp
private protectedLớp con trong cùng assemblyMới C# 7.2
 
public class SinhVien
{
    // Fields - thường là private
    private string _maSV;
    private string _hoTen;
    
    // Properties - public để truy cập từ bên ngoài
    public string MaSV => _maSV;
    public string HoTen => _hoTen;
    
    // Internal - dùng trong cùng dự án
    internal string LopHoc { get; set; }
    
    // Protected - cho lớp con
    protected double DiemTrungBinh { get; set; }
    
    // Private - chỉ dùng trong class
    private void ValidateData() { }
}

9.7. Thành phần tĩnh (Static) (0.2 giờ)

a. Biến static:

public class SinhVien
{
    private static int _soLuong = 0;  // Dùng chung cho tất cả đối tượng
    
    public SinhVien()
    {
        _soLuong++;  // Tăng mỗi lần tạo đối tượng mới
    }
    
    public static int SoLuong => _soLuong;  // Read-only
}

b. Phương thức static:

public class MathHelper
{
    // Không cần tạo đối tượng để gọi
    public static int TinhTong(int a, int b) => a + b;
    public static double TinhTrungBinh(double a, double b) => (a + b) / 2;
    public static bool IsEven(int n) => n % 2 == 0;
}

// Sử dụng
int tong = MathHelper.TinhTong(5, 3);  // Không cần new

c. Lớp static:

public static class StringHelper
{
    public static string VietHoaDau(string s)
    {
        if (string.IsNullOrEmpty(s)) return s;
        return char.ToUpper(s[0]) + s.Substring(1).ToLower();
    }
    
    public static string ChuanHoaTen(string ten)
    {
        ten = ten.Trim();
        while (ten.Contains("  "))
            ten = ten.Replace("  ", " ");
        return ten;
    }
}

d. Quy tắc sử dụng static:

  • Static method không thể truy cập non-static thành phần

  • Non-static method có thể truy cập static thành phần

  • Static constructor chạy 1 lần duy nhất

9.8. Garbage Collection – Quản lý bộ nhớ (0.2 giờ)

Khái niệm: .NET tự động quản lý bộ nhớ thông qua Garbage Collector (GC)

Nguyên lý hoạt động:

  1. Cấp phát bộ nhớ cho đối tượng trên Managed Heap

  2. GC tự động giải phóng bộ nhớ khi đối tượng không còn tham chiếu

  3. Không cần dùng delete hay free như C/C++

Hàm hủy (Destructor/Finalizer):

public class ResourceHandler
{
    // Destructor - được GC gọi khi giải phóng đối tượng
    ~ResourceHandler()
    {
        // Giải phóng tài nguyên không managed
        Console.WriteLine("Đối tượng bị giải phóng");
    }
}

IDisposable Interface:

public class FileHandler : IDisposable
{
    private FileStream _file;
    
    public void Dispose()
    {
        if (_file != null)
        {
            _file.Dispose();
            _file = null;
        }
        GC.SuppressFinalize(this);  // Không cần gọi finalizer
    }
}

// Sử dụng
using (FileHandler fh = new FileHandler())
{
    // Tự động gọi Dispose() khi kết thúc block
}

Bài tập thực hành

CẤU TRÚC SOLUTION CHO BÀI 9

LapTrinhHuongDoiTuong (Solution)
│
├── Bai1_SinhVien (Project)           ← Bài tập 1: Xây dựng lớp SinhVien
│   ├── Models/
│   │   └── SinhVien.cs
│   └── Program.cs                    ← Test SinhVien
│
├── Bai2_SanPham (Project)            ← Bài tập 2: Xây dựng lớp SanPham
│   ├── Models/
│   │   └── SanPham.cs
│   └── Program.cs                    ← Test SanPham
│
├── Bai3_TaiKhoan (Project)           ← Bài tập 3: Xây dựng lớp TaiKhoan
│   ├── Models/
│   │   └── TaiKhoanNganHang.cs
│   └── Program.cs                    ← Test TaiKhoan
│
├── Bai4_Validator (Project)          ← Bài tập 4: Lớp Validator (Static)
│   ├── Helpers/
│   │   └── Validator.cs
│   └── Program.cs                    ← Test Validator
│
├── Bai5_StringHelper (Project)       ← Bài tập 5: Lớp StringHelper (Static)
│   ├── Helpers/
│   │   └── StringHelper.cs
│   └── Program.cs                    ← Test StringHelper
│
├── Bai6_QuanLySinhVien (Project)     ← Bài tập 6: Quản lý danh sách SV
│   ├── Models/
│   │   ├── SinhVien.cs
│   │   └── QuanLySinhVien.cs
│   └── Program.cs                    ← Test Quản lý
│
└── Bai7_AppSinhVien (Project)        ← Bài tập 7: Ứng dụng Console hoàn chỉnh
    ├── Models/
    │   ├── SinhVien.cs
    │   └── QuanLySinhVien.cs
    └── Program.cs                    ← Menu chạy chương trình

Bài tập 1: Xây dựng lớp SinhVien đầy đủ

Bài tập 2:Xây dựng lớp SanPham

Bài tập 3:Xây dựng lớp TaiKhoan

Bài tập 4:Xây dựng lớp Validator

Bài tập 5:Xây dựng lớp StringHelper

Bài tập 6: Quản lý danh sách SinhVien với CRUD

Bài tập 7: Chương trình Quản lý Sinh viên