Late Binding (Gọi muộn / Dynamic Polymorphism) là cơ chế quyết định phương thức nào được gọi tại runtime thay vì compile-time. Trong C#, đạt được qua:
- Virtual/Override: Polymorphism chuẩn OOP.
- Abstract class/Interface: Contract bắt buộc implement.
dynamic(C# 4+): DLR (Dynamic Language Runtime), bỏ qua compile-time checking.- Reflection:
MethodInfo.Invoke().
Ví dụ: Virtual/Override (Polymorphism chuẩn)
using System;
namespace PolymorphismDemo
{
abstract class Shape
{
protected int Width, Height;
public Shape(int w = 0, int h = 0) { Width = w; Height = h; }
public abstract int Area(); // Abstract method - bắt buộc override
}
class Rectangle : Shape
{
public Rectangle(int w, int h) : base(w, h) { }
public override int Area() => Width * Height;
}
class Triangle : Shape
{
public Triangle(int w, int h) : base(w, h) { }
public override int Area() => Width * Height / 2;
}
class Caller
{
// Late binding: method Area() được quyết định tại runtime
public void CallArea(Shape shape)
{
Console.WriteLine($"{shape.GetType().Name} area: {shape.Area()}");
}
}
class Program
{
static void Main()
{
Caller caller = new Caller();
caller.CallArea(new Rectangle(10, 7)); // Rectangle.Area() gọi ở runtime
caller.CallArea(new Triangle(10, 5)); // Triangle.Area() gọi ở runtime
// Danh sách shape - polymorphism
Shape[] shapes = { new Rectangle(5, 5), new Triangle(4, 6) };
foreach (var s in shapes)
Console.WriteLine($"{s.GetType().Name}: {s.Area()}");
}
}
}
Kết quả
Rectangle area: 70 Triangle area: 25 Rectangle: 25 Triangle: 12
Late Binding với dynamic (C# 4+)
using System;
class Duck
{
public void Quack() => Console.WriteLine("Quack!");
public void Fly() => Console.WriteLine("Flying!");
}
class Robot
{
public void Quack() => Console.WriteLine("Beep boop!");
// Không có Fly()
}
class Program
{
static void Main()
{
dynamic duck = new Duck();
dynamic robot = new Robot();
MakeItQuack(duck); // OK: Duck có Quack()
MakeItQuack(robot); // OK: Robot có Quack()
// MakeItFly(duck); // OK
// MakeItFly(robot); // RuntimeBinderException: Robot không có Fly()
}
static void MakeItQuack(dynamic obj)
{
obj.Quack(); // Resolved tại runtime
}
}
So sánh Early Binding vs Late Binding
| Đặc điểm | Early Binding (Static) | Late Binding (Dynamic) |
|---|---|---|
| Thời điểm quyết định | Compile-time | Runtime |
| Cơ chế | Method overloading, non-virtual call | Virtual/override, dynamic, reflection |
| Hiệu năng | Nhanh (direct call, inline) | Chậm hơn (v-table lookup, DLR cache) |
| Type safety | Compile-time check | Runtime error nếu missing member |
| Linh hoạt | Cứng | Mềm (plugin, scripting, COM interop) |
Khi nào dùng Late Binding?
- Plugin/Extension system (load assembly động).
- Interop COM, JavaScript, Python (IronPython).
- Generic code xử lý kiểu không biết trước.
- Testing/Mocking.
Lưu ý: Lạm dụng dynamic làm code khó debug, mất IntelliSense, dễ bug runtime. Ưu tiên virtual/override hoặc interface cho polymorphism chuẩn.