명시적 인터페이스 구현(C# 프로그래밍 가이드)

클래스가 시그니처가 동일한 멤버를 포함하는 두 인터페이스를 구현하는 경우, 해당 멤버를 클래스에 구현하면 양쪽 인터페이스 모두가 해당 멤버를 구현에 사용합니다. 다음 예제에서 Paint에 대한 모든 호출은 같은 메서드를 호출합니다. 이 첫 번째 샘플에서는 다음 형식을 정의합니다.

public interface IControl
{
    void Paint();
}
public interface ISurface
{
    void Paint();
}
public class SampleClass : IControl, ISurface
{
    // Both ISurface.Paint and IControl.Paint call this method.
    public void Paint()
    {
        Console.WriteLine("Paint method in SampleClass");
    }
}

다음 샘플에서는 다음 메서드를 호출합니다.

SampleClass sample = new SampleClass();
IControl control = sample;
ISurface surface = sample;

// The following lines all call the same method.
sample.Paint();
control.Paint();
surface.Paint();

// Output:
// Paint method in SampleClass
// Paint method in SampleClass
// Paint method in SampleClass

그러나 두 인터페이스에 대해 모두 동일한 구현을 호출하지 않으려고 할 수 있습니다. 사용 중인 인터페이스에 따라 다른 구현을 호출하기 위해 인터페이스 멤버를 명시적으로 구현할 수 있습니다. 명시적 인터페이스 구현은 지정된 인터페이스를 통해서만 호출되는 클래스 멤버입니다. 클래스 이름 앞에 인터페이스 이름과 마침표를 추가하여 클래스 멤버의 이름을 지정합니다. 예를 들어:

public class SampleClass : IControl, ISurface
{
    void IControl.Paint()
    {
        System.Console.WriteLine("IControl.Paint");
    }
    void ISurface.Paint()
    {
        System.Console.WriteLine("ISurface.Paint");
    }
}

클래스 멤버 IControl.PaintIControl 인터페이스를 통해서만 사용할 수 있고 ISurface.PaintISurface를 통해서만 사용할 수 있습니다. 두 메서드 구현은 서로 별개이며 어느 쪽도 클래스에서 직접 사용할 수 없습니다. 예를 들어:

SampleClass sample = new SampleClass();
IControl control = sample;
ISurface surface = sample;

// The following lines all call the same method.
//sample.Paint(); // Compiler error.
control.Paint();  // Calls IControl.Paint on SampleClass.
surface.Paint();  // Calls ISurface.Paint on SampleClass.

// Output:
// IControl.Paint
// ISurface.Paint

명시적 구현은 두 인터페이스가 속성이나 메서드와 같이 동일한 이름을 가진 서로 다른 멤버를 선언하는 사례를 해결하는 데도 사용됩니다. 두 인터페이스를 모두 구현하려면 클래스는 P 속성이나 P 메서드 중 하나 또는 둘 다에 대해 명시적 구현을 사용하여 컴파일러 오류를 방지해야 합니다. 예를 들어:

interface ILeft
{
    int P { get;}
}
interface IRight
{
    int P();
}

class Middle : ILeft, IRight
{
    public int P() { return 0; }
    int ILeft.P { get { return 0; } }
}

명시적 인터페이스 구현은 정의되어 있는 형식의 멤버로 액세스할 수 없기 때문에 해당 구현에는 액세스 한정자가 없습니다. 대신 인터페이스 인스턴스를 통해 호출되는 경우에만 액세스할 수 있습니다. 명시적 인터페이스 구현의 액세스 한정자를 지정하면 컴파일러 오류 CS0106이 발생합니다. 자세한 내용은 interface(C# 참조)를 참조하세요.

인터페이스에 선언된 멤버에 대한 구현을 정의할 수 있습니다. 클래스가 인터페이스로부터 메서드 구현을 상속하는 경우, 해당 메서드는 인터페이스 형식의 참조를 통해서만 액세스할 수 있습니다. 상속된 멤버는 public 인터페이스의 일부로 표시되지 않습니다. 다음 샘플은 인터페이스에 메서드에 대한 기본 구현을 정의합니다.

public interface IControl
{
    void Paint() => Console.WriteLine("Default Paint method");
}
public class SampleClass : IControl
{
    // Paint() is inherited from IControl.
}

다음 샘플은 기본 구현을 호출합니다.

var sample = new SampleClass();
//sample.Paint();// "Paint" isn't accessible.
var control = sample as IControl;
control.Paint();

IControl 인터페이스를 구현하는 모든 클래스는 기본 Paint 메서드를 public 메서드로 또는 명시적 인터페이스 구현으로 재정의할 수 있습니다.

참고 항목