Trong lập trình hướng đối tượng (OOP), đặc biệt khi bạn phát triển ứng dụng bằng .NET Core, bạn sẽ thường gặp ba khái niệm quan trọng:
- Class
- Abstract Class
- Interface
Chúng đều được dùng để mô hình hóa đối tượng và hành vi, nhưng cách sử dụng hoàn toàn khác nhau.
Bài viết này sẽ giúp bạn hiểu rõ bản chất, sự khác nhau và cách dùng chính xác trong thực tế.
✅ Class (Lớp) là gì?
Class là bản thiết kế (blueprint) để tạo ra đối tượng (object).
Bên trong class có thể chứa:
✔ Properties
✔ Methods (hàm)
✔ Fields
✔ Constructors
✔ Sự kiện, indexer, virtual methods...
📌 Ví dụ:
public class Animal
{
public string Name { get; set; }
public void Speak()
{
Console.WriteLine("Some sound");
}
}

Bạn có thể khởi tạo object:
var dog = new Animal();
dog.Name = "Dog";
dog.Speak();

=> Thần chú: là thực thểm có thể khởi tạo instance, có thể tự triển khai method bên trong
✅ Abstract Class – Lớp trừu tượng
Là lớp dùng để kế thừa, không thể tạo object trực tiếp bằng new.
Đặc điểm:
✔ Có thể chứa methods bình thường
✔ Có thể chứa abstract methods — bắt buộc class con override
✔ Có constructor
✔ Dùng để chia sẻ logic chung cho các lớp con
❌ Chỉ kế thừa 1 abstract class
📌 Ví dụ:
public abstract class Animal
{
public string Name { get; set; }
public abstract void Speak();
public void Eat()
{
Console.WriteLine($"{Name} is eating.");
}
}
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}

=> thần chú: không phải thực thể, không thể tạo instance, có thể tự triển khai method bên trong, method thuộc tính abstract bắt buộc thằng kế thừa phải override
✅ Interface – Giao diện
Là bản hợp đồng chỉ mô tả hành vi, không có trạng thái nội tại.
Đặc điểm:
✔ Chỉ chứa phần khai báo hàm (không có logic)
✔ Không có constructor
✔ Một class có thể implement nhiều interface
✔ Giúp cấu trúc phần mềm linh hoạt (Dependency Injection rất hay dùng)
⭕ Từ C# 8 trở lên: interface có thể có default method
📌 Ví dụ:
public interface IFly
{
void Fly();
}
public class Bird : Animal, IFly
{
public override void Speak() => Console.WriteLine("Chip chip!");
public void Fly() => Console.WriteLine("Bird is flying!");
}

=> thần chú: không là thực thể, không thể tạo instance, không thể tự triển khai method
🔥 Bảng so sánh nhanh

🎯 Khi nào dùng cái nào?

Lý thuyết xong rồi vào thực hành thôi: làm tiếp video ngày 9 khởi tạo project .net core nè:
🧩 Ví dụ thực tế: Repository Pattern trong .NET Core
📌 Interface dùng để tạo quy tắc chung: Ví dụ mình có api login trong authcontroller. Nhưng nguyên tắc là không để logic chính trong tầng trong controller, người ta thường tạo 1 tầng riêng xử lý logic thường được gọi là business. Ở bài này mình hơi ăn gian 1 chút, sẽ tạm bỏ qua tầng service ha. Bài khác mình sẽ bổ sung.
[HttpPost]
public async Task<ApiResModel<LoginResponse>> Login(LoginRequest request)
{
var user = await _context.Users.AsNoTracking()
.FirstOrDefaultAsync(u => u.UserName == request.UserName);
if (user == null || user.PasswordHash != request.Password)
return new ApiResModel<LoginResponse>
{
Id = -1,
Message = "Account or password is not correct"
};
if(user.IsActive != true)
return new ApiResModel<LoginResponse>
{
Id = -1,
Message = "Account is inactive"
};
return new ApiResModel<LoginResponse>
{
Data = _authService.GenerateJwtToken(new UserInfoJwt
{
UserId = user.UserId,
UserCode = user.UserName,
Email = user.Email,
Roles = new List<string> { "GetSession", "Payment", "User-Create", "User-Update", "User-Delete" },
FullName = "name"
}),
Id = 1,
Message = "Success"
};
}
Sau đó mình tạo 1 folder Business, rồi tạo class AuthBusiness.cs
public interface IAuthBusiness
{
Task<ApiResModel<LoginResponse>> Login(LoginRequest request);
}
public class AuthBusiness : IAuthBusiness
{
private readonly IAuthService _authService;
private readonly MyDbContext _context;
public AuthBusiness(IAuthService authService, MyDbContext context)
{
_authService = authService;
_context = context;
}
public async Task<ApiResModel<LoginResponse>> Login(LoginRequest request)
{
var user = await _context.Users.AsNoTracking()
.FirstOrDefaultAsync(u => u.UserName == request.UserName);
if (user == null || user.PasswordHash != request.Password)
return new ApiResModel<LoginResponse>
{
Id = -1,
Message = "Account or password is not correct"
};
if (user.IsActive != true)
return new ApiResModel<LoginResponse>
{
Id = -1,
Message = "Account is inactive"
};
return new ApiResModel<LoginResponse>
{
Data = _authService.GenerateJwtToken(new UserInfoJwt
{
UserId = user.UserId,
UserCode = user.UserName,
Email = user.Email,
Roles = new List<string> { "GetSession", "Payment", "User-Create", "User-Update", "User-Delete" },
FullName = "name"
}),
Id = 1,
Message = "Success"
};
}
}

Sau khi xong thì tiến hành đăng ký:
builder.Services.AddScoped<IAuthBusiness, AuthBusiness>();
Sau đó chỉ cần khai báo trong authcontroller và dùng thôi:
private readonly IAuthBusiness _authBusiness;
public AuthController(IHttpContextAccessor _httpContextAccessor,
IAuthBusiness authBusiness) : base(_httpContextAccessor)
{
_authBusiness = authBusiness;
}
[HttpPost]
public async Task<ApiResModel<LoginResponse>> Login(LoginRequest request)
{
return await _authBusiness.Login(request);
}

✅ Kết luận

Hiểu rõ 3 khái niệm này giúp bạn:
- Thiết kế kiến trúc tốt hơn
- Dễ bảo trì và mở rộng
- Áp dụng DI/Repository/SOLID hiệu quả