Inheritance (Kế thừa) cho phép định nghĩa class mới (derived class) dựa trên class hiện có (base class), tái sử dụng code, mở rộng hành vi. C# hỗ trợ single inheritance cho class (chỉ kế thừa 1 base class), nhưng implement nhiều interface.
Khái niệm cốt lõi
- Base class (Parent/Superclass): Class được kế thừa.
- Derived class (Child/Subclass): Class kế thừa.
:ký hiệu kế thừa:class Derived : Base.base: Truy cập member của base class.virtual/override: Polymorphism.sealed: Ngăn không cho kế thừa/override thêm.abstract: Class/method bắt buộc override, không tạo instance.
Ví dụ: Shape → Rectangle
using System;
namespace InheritanceDemo
{
// Base class
class Shape
{
protected int Width; // protected: derived class truy cập được
protected int Height;
public void SetWidth(int w) => Width = w;
public void SetHeight(int h) => Height = h;
// Virtual method: cho phép override
public virtual void Display()
=> Console.WriteLine($"Shape: {Width}x{Height}");
}
// Derived class
class Rectangle : Shape
{
public int GetArea() => Width * Height;
// Override virtual method
public override void Display()
{
base.Display(); // Gọi base implementation
Console.WriteLine($"Rectangle Area: {GetArea()}");
}
}
// Derived class khác
class Triangle : Shape
{
public int GetArea() => Width * Height / 2;
public override void Display()
{
Console.WriteLine($"Triangle: {Width}x{Height}, Area: {GetArea()}");
}
}
class Program
{
static void Main()
{
Rectangle rect = new Rectangle();
rect.SetWidth(5);
rect.SetHeight(7);
rect.Display();
Console.WriteLine();
Triangle tri = new Triangle();
tri.SetWidth(10);
tri.SetHeight(6);
tri.Display();
// Polymorphism
Console.WriteLine("\n--- Polymorphism ---");
Shape[] shapes = { new Rectangle { Width = 3, Height = 4 }, new Triangle { Width = 5, Height = 8 } };
foreach (var s in shapes)
s.Display(); // Gọi override method tại runtime
}
}
}
Kết quả
Shape: 5x7 Rectangle Area: 35 Triangle: 10x6, Area: 30 --- Polymorphism --- Shape: 3x4 Rectangle Area: 12 Triangle: 5x8, Area: 20
Constructor trong kế thừa
class Base
{
public Base() { Console.WriteLine("Base()"); }
public Base(int x) { Console.WriteLine($"Base({x})"); }
}
class Derived : Base
{
public Derived() { Console.WriteLine("Derived()"); } // Gọi Base() ngầm
public Derived(int x, int y) : base(x) { Console.WriteLine($"Derived({x},{y})"); } // Gọi Base(x)
}
Access Modifiers trong kế thừa
| Modifier | Base class | Derived class | Outside |
|---|---|---|---|
public | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ❌ |
internal | ✅ | ✅ (cùng assembly) | ✅ (cùng assembly) |
protected internal | ✅ | ✅ | ✅ (cùng assembly) |
private protected | ✅ | ✅ (cùng assembly) | ❌ |
private | ✅ | ❌ | ❌ |
Best Practices
- "Favor composition over inheritance" (GoF) - dùng interface + DI thay vì kế thừa sâu.
- Base class nên
abstractnếu không có ý nghĩa standalone. - Dùng
sealedcho class không muốn ai kế thừa, hoặcsealed overridecho method. - Gọi
base.Constructor()tường minh khi base có parameterized constructor.