c# - 인스턴스 - 파생 클래스를 기본 클래스의 인터페이스 구현으로 명시 적으로 표시



c# 인터페이스 인스턴스 (2)

이는 C # 5 사양의 13.4.4 ~ 13.4.6 섹션에서 설명합니다. 관련 섹션은 아래에 인용되어 있지만 기본적으로 클래스가 인터페이스를 구현한다고 명시 적으로 명시하면 인터페이스 매핑이 다시 트리거되므로 컴파일러는 해당 클래스를 각 인터페이스 멤버가 매핑되는 구현을 해결하는 데 사용할 클래스로 사용합니다.

13.4.4 인터페이스 매핑

클래스 또는 구조체는 클래스 또는 구조체의 기본 클래스 목록에 나열된 인터페이스의 모든 구성원에 대한 구현을 제공해야합니다. 구현 클래스 또는 구조체에서 인터페이스 구성원의 구현을 찾는 프로세스를 인터페이스 매핑이라고합니다.

클래스 또는 구조체 C 대한 인터페이스 매핑 CC 의 기본 클래스 목록에 지정된 각 인터페이스의 각 멤버에 대한 구현을 찾습니다. I 가 멤버 M 이 선언 된 인터페이스 인 특정 인터페이스 멤버 IM 의 구현은 C 시작하고 매치가있을 때까지 C 각 연속 기본 클래스에 대해 반복하여 각 클래스 또는 구조체 S 를 검사하여 결정됩니다 :

  • SIM 과 일치하는 명시 적 인터페이스 구성원 구현의 선언이 포함 된 경우이 구성원은 IM 구현입니다.
  • 그렇지 않으면 S 에 M과 일치하는 비 정적 공용 멤버의 선언이 포함되어 있으면이 멤버는 IM 의 구현입니다. 둘 이상의 구성원이 일치하는 경우 어떤 구성원이 IM 구현인지는 지정되지 않습니다. 이 상황은 S 가 제네릭 형식으로 선언 된 두 멤버가 다른 서명을 가지고 있지만 형식 인수가 해당 서명을 동일하게 만드는 생성 된 형식 인 경우에만 발생할 수 있습니다.

...

13.4.5 인터페이스 구현 상속

클래스는 기본 클래스에서 제공하는 모든 인터페이스 구현을 상속합니다. 인터페이스를 명시 적으로 다시 구현하지 않고 파생 클래스는 기본 클래스에서 상속 된 인터페이스 매핑을 어떤 식 으로든 변경할 수 없습니다. 예를 들어, 선언문

interface IControl
{
    void Paint();
}
class Control: IControl
{
    public void Paint() {...}
}
class TextBox: Control
{
    new public void Paint() {...}
}

TextBoxPaint 메서드는 ControlPaint 메서드를 숨기지 Control.PaintIControl.Paint 의 매핑을 변경하지 않으며 클래스 인스턴스와 인터페이스 인스턴스를 통해 Paint 를 호출하면 다음과 같은 효과가 있습니다

Control c = new Control();
TextBox t = new TextBox();
IControl ic = c;
IControl it = t;
c.Paint();            // invokes Control.Paint();
t.Paint();            // invokes TextBox.Paint();
ic.Paint();           // invokes Control.Paint();
it.Paint();           // invokes Control.Paint();

...

13.4.6 인터페이스 재 구현

인터페이스 구현을 상속받은 클래스는 기본 클래스 목록에 인터페이스를 포함시켜 인터페이스를 다시 구현할 수 있습니다.

인터페이스의 재 구현은 인터페이스의 초기 구현과 완전히 동일한 인터페이스 매핑 규칙을 따릅니다. 따라서 상속 된 인터페이스 매핑은 인터페이스를 다시 구현하기 위해 설정된 인터페이스 매핑에 아무런 영향을 미치지 않습니다. 예를 들어, 선언문

interface IControl
{
    void Paint();
}
class Control: IControl
{
    void IControl.Paint() {...}
}
class MyControl: Control, IControl
{
    public void Paint() {}
}

Control.IControl.PaintControl.IControl.Paint IControl.Paint 를 매핑해도 IControl.PaintMyControl.Paint 매핑하는 MyControl 의 다시 구현에는 영향을 미치지 않습니다.

interface IBase
{
    string Name { get; }
}

class Base : IBase
{
    public Base() => this.Name = "Base";
    public string Name { get; }
}

class Derived : Base//, IBase
{
    public Derived() => this.Name = "Derived";
    public new string Name { get; }
}


class Program
{
    static void Main(string[] args)
    {
        IBase o = new Derived();
        Console.WriteLine(o.Name);
    }
}

이 경우 출력은 "Base"가됩니다.

Derived가 IBase (실제로 이미 기본 클래스 Base에 의해 구현되고 그러한 주석이 쓸모없는 것처럼 보임)를 구현한다고 명시 적으로 명시하면 출력은 "파생 됨"

class Derived : Base, IBase
{
    public Derived() => this.Name = "Derived";
    public new string Name { get; }
}

그런 행동에 대한 이유는 무엇입니까?

VS 15.3.5, C # 7


Answer #1

DerivedIBase 구현하지 않고 new string Name 선언하면 Derived.NameIBase.Name 이 논리적으로 동일하지 않음을 의미합니다. 따라서 IBase.Name 에 액세스하면 IBase.Name 구현하는 Base 클래스에서 IBase . new string Name 속성을 제거하면 Derived.Name = Base.Name = IBase.Name 이므로 이제 출력이 Derived 됩니다. IBase 구현하면 Derived.Name = IBase.Name 이므로 출력은 Derived 가됩니다. oDerived 캐스팅하면 출력이 Derived 됩니다. 이제 Derived.Name 대신 Derived.Name 에 액세스하고 있기 때문입니다.





interface