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
Ví dụ : Chiếc xe ô tô
Trạng thái (State): màu sắc, số ghế, loại động cơ, tốc độ hiện tại.
Hành vi (Behavior): chạy, dừng, bấm còi, bật đèn.
Định danh (Identity): biển số xe, số khung, số máy – giúp phân biệt xe này với xe khác.
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 |
Một ví dụ về lập trình hướng đối tượng (OOP) trong đời sống là chiếc xe ô tô 🚗.
Lớp (Class): tưởng tượng như “bản thiết kế” của một chiếc xe. Trong bản thiết kế có ghi rõ xe có động cơ, bánh xe, màu sơn, và các chức năng như chạy, dừng, bấm còi.
Đối tượng (Object): chính là chiếc xe cụ thể ngoài đời. Ví dụ: một chiếc Toyota màu đỏ, hay một chiếc VinFast màu trắng. Cả hai đều được tạo ra từ “lớp Xe” nhưng có đặc điểm riêng.
Đóng gói (Encapsulation): tất cả thông tin và chức năng của xe (động cơ, tốc độ, phanh) đều nằm gọn trong chiếc xe đó. Người lái chỉ cần dùng vô lăng, bàn đạp, không cần biết chi tiết bên trong.
Kế thừa (Inheritance): nếu có lớp “Xe”, ta có thể tạo lớp “Xe điện” kế thừa từ nó, nhưng thêm thuộc tính riêng như pin thay vì động cơ xăng.
Đa hình (Polymorphism): khi bạn nhấn nút “khởi động”, xe xăng sẽ nổ máy, còn xe điện sẽ bật pin – cùng một hành động nhưng cách thực hiện khác nhau.
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:
{ // 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ể:
{ // 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:
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 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 NhanVien(string ma, string ten, double luong) { MaNV = ma; HoTen = ten; LuongCoBan = luong; } }
c. Constructor overloading (nạp chồng):
{ // 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 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:
{ // 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
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 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:
{ 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:
{ 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 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 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ờ)
| Modifier | Mô tả | Ví dụ sử dụng |
|---|---|---|
public | Truy cập từ mọi nơi | API, interface công khai |
private | Chỉ trong cùng lớp | Fields, helper methods |
protected | Trong lớp và lớp con | Dùng trong kế thừa |
internal | Trong cùng assembly | Thư viện nội bộ |
protected internal | Lớp con hoặc cùng assembly | Kết hợp |
private protected | Lớp con trong cùng assembly | Mới C# 7.2 |
{ // 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:
{ 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:
{ // 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 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:
Cấp phát bộ nhớ cho đối tượng trên Managed Heap
GC tự động giải phóng bộ nhớ khi đối tượng không còn tham chiếu
Không cần dùng
deletehayfreenhư C/C++
Hàm hủy (Destructor/Finalizer):
{ // 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:
{ 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
│
├── 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ìnhBà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