2012-01-11 4 views
5

누군가이 두 예제의 차이점을 설명해 주시겠습니까?다형성/재정의

클래스 A

protected virtual string GetData()

클래스 B

private override string GetData()

그리고 다음

클래스 A 가정

protected string GetData()

클래스 B

private string GetData()

그 '클래스 A'에서 '클래스 B'상속한다.

수퍼 클래스에서 virtual을 사용해야하고 메서드를 재정의하려면 서브 클래스에서 override을 사용해야한다고 생각했지만 키워드를 제거하고 프로그램을 컴파일 해 보았습니다. 차이가 있다면 정확히 무엇입니까?

+0

B.GetData() 아래에 구불 구불 한가 보입니까? 보기 + 오류 목록에 경고가 표시됩니까? 놓치기 힘든, 당신이하고있는 것을 알 때 * new * 키워드를 사용하십시오. –

+1

첫 번째 예제에서 B의 메서드는 private 일 수 없습니다. 컴파일되지 않습니다. – TrueWill

답변

4

표시 한 두 번째 예제에서는 부모의 GetData를 숨기고 무시합니다.

예 :

private class Base 
{ 
    public virtual void Test() 
    { 
     Console.WriteLine("Base"); 
    } 

    public void Test2() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

private class Derived : Base 
{ 
    public override void Test() 
    { 
     Console.WriteLine("Derived"); 
    } 

    public void Test2() 
    { 
     Console.WriteLine("Derived"); 
    } 
} 

static void Main() 
{ 
    Base b = new Base(); 
    Derived d = new Derived(); 
    Base dInB = new Derived(); 

    b.Test(); 
    d.Test(); 
    dInB.Test(); 

    b.Test2(); 
    d.Test2(); 
    dInB.Test2(); 

    Console.ReadKey(true); 
} 

그것은 출력 : 그것은 파생 클래스에서 public new void Test2()new 키워드를 사용해야하기 때문에

Base // Base.Test() 
Derived // Derived.Test() 
Derived // Derived.Test() 
Base // Base.Test2() 
Derived // Derived.Test2() 
Base // You think you're calling Derived.Test2(), but you actually call Base.Test2() 

사실이 샘플은 유효하지 않습니다.

이것은 연산자 오버로딩과 동일하게 작동합니다. 실제로 아무 것도 무시하지 않습니다. 정확한 유형이 Derived이면 새 메소드가 호출됩니다.

멤버를 숨기는 데주의해야합니다. 클래스를 재정의하거나 (인터페이스)를 구현하는 것과 같은 것이 아닙니다.정확히 유형이있는 경우에만new메쏘드를 호출합니다. 그렇지 않으면 여전히 기본 유형의 메소드가 호출됩니다.

+0

고마워, 그걸 정리하는 데 도움이 됐어! –

+0

당신은 환영합니다 :) – Aidiakapi

3

차이점은 첫 번째 경우는 무시하고 두 번째 경우는 완전히 다른 것입니다. 두 번째 경우에 다른 한편으로

class B: A 
{ 
    void Foo() 
    { 
     B b = new B(); 
     A a = b; 

     a.GetData() //B's GetData() will be called 
     b.GetData() //B's GetData() will be called 
    } 
} 

: 첫 번째 경우에

두 번째 경우

class B: A 
{ 
    void Foo() 
    { 
     B b = new B(); 
     A a = b; 

     a.GetData() //A's GetData() will be called 
     b.GetData() //B's GetData() will be called 
    } 
} 

단순히 GetData의 (의 구현을 숨기고있다)하지만 당신은 항상 것입니다 변수가 유형 B의 인스턴스를 참조하는 경우에도 유형이 A 인 변수를 통해 A의 구현을 호출 할 수 있어야합니다. 이는 대체가 작동하는 방식과 완전히 다릅니다.

+0

설명해 주셔서 감사합니다! –

0
public class A 
{ 
    public virtual string GetData() { return "A";} 
} 

public class B : A 
{ 
    public override string GetData() { return "B"; } 
} 

다음 코드 블럭에서와 같이 클래스를 사용한다면 어떻게 될 것으로 기대합니까?

 A a = new A(); 
     B b = new B(); 
     A c = new B(); 

     Console.WriteLine(a.GetData()); 
     Console.WriteLine(b.GetData()); 
     Console.WriteLine(c.GetData()); 

"A" "B" "B"가 인쇄됩니다. 변수 c는 A 유형으로 저장되지만 메소드를 실행할 때 코드는 "실제"구현으로 해석됩니다. (가상 기능 표 및 해결 원리는 google을 참조하십시오.)

아래 코드에서와 같이 가상 및 재정의를 사용하지 않으면 "A" "B" "A"가 인쇄됩니다.

public class A 
{ 
    public string GetData() { return "A";} 
} 

public class B : A 
{ 
    public new string GetData() { return "B"; } 
}