Compile-time Polymorphism (Đa hình tĩnh / Static Binding / Early Binding) là đa hình được giải quyết tại compile-time. C# hỗ trợ qua hai cơ chế:
- Method Overloading (Nạp chồng phương thức)
- Operator Overloading (Nạp chồng toán tử)
1. Method Overloading
Nhiều phương thức cùng tên, khác signature (số lượng/kiểu tham số).
using System;
class PrintData
{
public void Print(int i)
=> Console.WriteLine($"Printing int: {i}");
public void Print(double f)
=> Console.WriteLine($"Printing double: {f}");
public void Print(string s)
=> Console.WriteLine($"Printing string: {s}");
// Overload với params
public void Print(params object[] args)
=> Console.WriteLine($"Printing array: {string.Join(", ", args)}");
}
class Program
{
static void Main()
{
PrintData p = new PrintData();
p.Print(5); // Gọi Print(int)
p.Print(500.263); // Gọi Print(double)
p.Print("Hello C#"); // Gọi Print(string)
p.Print(1, 2, 3); // Gọi Print(params object[])
}
}
2. Operator Overloading
Định nghĩa hành vi toán tử (+, -, ==, !=, <, >, implicit/explicit conversion...) cho kiểu tự định nghĩa.
using System;
public struct Complex
{
public double Real { get; }
public double Imag { get; }
public Complex(double real, double imag)
{
Real = real;
Imag = imag;
}
// Overload toán tử +
public static Complex operator +(Complex a, Complex b)
=> new Complex(a.Real + b.Real, a.Imag + b.Imag);
// Overload toán tử *
public static Complex operator *(Complex a, Complex b)
=> new Complex(
a.Real * b.Real - a.Imag * b.Imag,
a.Real * b.Imag + a.Imag * b.Real
);
// Implicit conversion từ double
public static implicit operator Complex(double d)
=> new Complex(d, 0);
// Explicit conversion sang double (magnitude)
public static explicit operator double(Complex c)
=> Math.Sqrt(c.Real * c.Real + c.Imag * c.Imag);
public override string ToString()
=> $"{Real} + {Imag}i";
}
class Program
{
static void Main()
{
Complex c1 = new Complex(2, 3);
Complex c2 = new Complex(1, 4);
Complex sum = c1 + c2; // operator +
Complex prod = c1 * c2; // operator *
Complex fromDouble = 5.0; // implicit conversion
double magnitude = (double)c1; // explicit conversion
Console.WriteLine($"c1 = {c1}");
Console.WriteLine($"c2 = {c2}");
Console.WriteLine($"c1 + c2 = {sum}");
Console.WriteLine($"c1 * c2 = {prod}");
Console.WriteLine($"double 5.0 -> Complex: {fromDouble}");
Console.WriteLine($"|c1| = {magnitude}");
}
}
Kết quả
c1 = 2 + 3i c2 = 1 + 4i c1 + c2 = 3 + 7i c1 * c2 = -10 + 11i double 5.0 -> Complex: 5 + 0i |c1| = 3.605551275463989
Quy tắc Operator Overloading
- Phải
public static. - Ít nhất một operand là kiểu chứa (containing type).
- Không overload:
=,.,?.,??,??=,?:,=>,as,is,typeof,sizeof,new,checked,unchecked,default,delegate,nameof. - Cặp so sánh phải overload cùng lúc:
==&!=,<&>,<=&>=. - Nếu overload
==, phải overrideEquals()vàGetHashCode().
So sánh Static vs Dynamic Polymorphism
| Đặc điểm | Static (Compile-time) | Dynamic (Runtime) |
|---|---|---|
| Cơ chế | Overloading (method/operator) | Virtual/Override, Interface |
| Quyết định | Compile-time (signature) | Runtime (v-table) |
| Hiệu năng | Nhanh hơn (có thể inline) | Chậm hơn (indirect call) |
| Linh hoạt | Cố định tại compile | Mở rộng tại runtime |