Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Đa hình tĩnh (Compile-time Polymorphism) trong C#

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ế:

  1. Method Overloading (Nạp chồng phương thức)
  2. 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 override Equals() và GetHashCode().

So sánh Static vs Dynamic Polymorphism

Đặc điểmStatic (Compile-time)Dynamic (Runtime)
Cơ chếOverloading (method/operator)Virtual/Override, Interface
Quyết địnhCompile-time (signature)Runtime (v-table)
Hiệu năngNhanh hơn (có thể inline)Chậm hơn (indirect call)
Linh hoạtCố định tại compileMở rộng tại runtime