2011-02-07 1 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 
    { 

    } 

출력은 : AAA방법 오버로딩 다형성

출력은가되도록 그것이 어떻게 든 방법 오버로딩을 사용할 수있다 : ABC? 당신은 C# 4를 사용하는 경우

답변

12

당신은 동적 입력을 사용할 수 있습니다

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

정적 타이핑 내에서 오버로드 확인은하지 실행시, 컴파일 시간에 수행된다. 구현을 위해

는 하나가 과부하 대신 의를 무시 를 사용하거나 위와 같이 동적 입력을 사용할 필요가 의사 결정시 선택합니다.

+1

컴파일 시간에 과부하 해결이 수행되지만 "B a"가 "B b"및 "C c"보다 우선 선택되는 이유는 무엇입니까? – Sandeep

+1

@Sandeep :'Main'에있는'a' 변수의 컴파일 타임 타입은리스트가'List '이기 때문에 A 만입니다. 그래서'Render (a)'는'Render (A a)'만을 선택할 수 있습니다. –

2

기본 (추상) 클래스에서 파생 된 A B C를 만들려면 해당 클래스에 각 A B C에서 렌더링 및 대체를 적절하게 정의합니다. Render(a)을 호출하는 대신 a.Render()이라고 부르십시오. 이것이 다형성이 작용하는 방식입니다.

13

다음은 해당 유형 내에서 형과 함께 작업 할 때 우리는 동작을 제어하는 ​​트릭을 수행한다고 :

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(); 
} 

그리고 당신은의에 첨가 될 수있는 유형의 정의 된 동작을 원하는 경우는 부모, 다음 예를 들어, 자신의 논리를 실행 한 후베이스에 구현 된 메소드를 호출

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

또 다른 방법이이 visitor pattern 함께 달성하기 : 당신이 같은 것을 을 달성 할 수 있습니다 양방향 메소드 호출 시스템을 사용하여 다형성 :

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); 
    } 
} 

이 방법의 장점은 효과적으로 각 유형의 올바른 과부하가 강력한 형식의 this 내부적으로 Render에 전달하여 호출 보장 (다형성을 달성 할 수 있다는 것입니다) 자신의 유형에 속하지 않는 논리 (예 : 시각적 렌더링 논리)를 유지하면서.