2011-02-07 33 views
9
class Program 
    { 
     static void Main(string[] args) 
     { 
      List<A> myList = new List<A> {new A(), new B(), new C()}; 

      foreach (var a in myList) 
      { 
       Render(a); 
      } 

      Console.ReadKey(); 
     } 

     private static void Render(A o) 
     { 
      Console.Write("A"); 
     } 

     private static void Render(B b) 
     { 
      Console.Write("B"); 
     } 

     private static void Render(C c) 
     { 
      Console.Write("C"); 
     } 
    } 

    class A 
    { 

    } 

    class B : A 
    { 

    } 

    class C : A 
    { 

    } 

Đầu ra là: AAAPhương pháp quá tải và đa hình

Có thể bằng cách nào đó sử dụng phương pháp quá tải, do đó sản lượng sẽ là: ABC?

Trả lời

12

Bạn có thể sử dụng gõ động nếu bạn đang sử dụng C# 4:

foreach (dynamic a in myList) 
{ 
    Render(a); 
} 

Trong gõ tĩnh, độ phân giải quá tải được thực hiện tại thời gian biên dịch, không phải ở thời gian thực hiện.

Để triển khai được chọn vào thời điểm quyết định, bạn phải sử dụng ghi đè thay vì quá tải hoặc sử dụng nhập động như trên.

+1

Mặc dù độ phân giải quá tải được thực hiện tại thời gian biên dịch tại sao "A a" được chọn trên "B b" và "C c". – Sandeep

+1

@Sandeep: Vì kiểu biên dịch của biến 'a' trong' Main' chỉ là A, bởi vì danh sách là một 'Danh sách '. Vì vậy, 'Render (a)' có thể * chỉ * chọn 'Render (A a)'. –

2

Tạo A B C xuất phát từ lớp cơ sở (trừu tượng), xác định trong lớp đó một phương thức Render và ghi đè đúng trong mỗi A B C. Thay vì gọi số Render(a), hãy gọi a.Render() đây là cách mà tính đa hình được cho là hoạt động.

13

Sau đây ta phải làm như lừa, nơi chúng tôi kiểm soát hành vi khi làm việc với một loại trong vòng loại rằng:

class A 
{ 
    public virtual void Render() 
    { 
     Console.WriteLine("A"); 
    } 
} 

class B : A 
{ 
    public override void Render() 
    { 
     Console.WriteLine("B"); 
    } 
} 

class C : A 
{ 
    public override void Render() 
    { 
     Console.WriteLine("C"); 
    } 
} 

static void Main(string[] args) 
{ 
    var myList = new List<A> { new A(), new B(), new C() }; 
    foreach (var a in myList) 
    { 
     a.Render(); 
    } 
    Console.ReadKey(); 
} 

Và nếu bạn muốn các hành vi được xác định của một loại là chất phụ gia như của mình phụ huynh, sau đó gọi phương thức thực hiện tại các cơ sở sau khi thực hiện logic riêng của bạn, ví dụ:

class B : A 
{ 
    public override void Render() 
    { 
     Console.WriteLine("B"); 
     base.Render(); 
    } 
} 
6

Một cách khác để thực hiện điều này là với visitor pattern: nó cho phép bạn để đạt được một cái gì đó giống như đa hình bằng cách sử dụng hai chiều hệ thống phương pháp gọi điện thoại:

interface IRenderable 
{ 
    AcceptForRender(Program renderer); 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var p = new Program(); 
     var myList = new List<IRenderable> {new A(), new B(), new C()}; 

     foreach (var a in myList) 
     { 
      a.AcceptForRender(p); 
     } 

     Console.ReadKey(); 
    } 

    public void Render(A o) 
    { 
     Console.Write("A"); 
    } 

    public void Render(B b) 
    { 
     Console.Write("B"); 
    } 

    public void Render(C c) 
    { 
     Console.Write("C"); 
    } 
} 

class A : IRenderable 
{ 
    public void AcceptForRender(Program renderer) 
    { 
     renderer.Render(this); 
    } 
} 

class B : IRenderable 
{ 
    public void AcceptForRender(Program renderer) 
    { 
     renderer.Render(this); 
    } 
} 

class C : IRenderable 
{ 
    public void AcceptForRender(Program renderer) 
    { 
     renderer.Render(this); 
    } 
} 

Ưu điểm của phương pháp này là nó cho phép bạn để đạt được hiệu quả đa hình (mỗi loại đảm bảo sự quá tải chính xác được gọi bằng cách truyền mạnh mẽ-gõ this để Render nội bộ) trong khi vẫn giữ logic không thuộc về các loại của bạn (ví dụ: logic hiển thị trực quan).

Các vấn đề liên quan