[c#] 인터페이스를 명시 적으로 구현하는 이유는 무엇입니까?
그렇다면 인터페이스를 명시 적으로 구현하는 좋은 사용 사례는 정확히 무엇일까요?
클래스를 사용하는 사람들이 intellisense에서 이러한 모든 메서드 / 속성을 볼 필요가 없도록하는 것입니까?
답변
동일한 메서드와 다른 구현으로 두 개의 인터페이스를 구현하는 경우 명시 적으로 구현해야합니다.
public interface IDoItFast
{
void Go();
}
public interface IDoItSlow
{
void Go();
}
public class JustDoIt : IDoItFast, IDoItSlow
{
void IDoItFast.Go()
{
}
void IDoItSlow.Go()
{
}
}
답변
선호하지 않는 회원을 숨기는 것이 유용합니다. 예를 들어 두 가지를 모두 구현 IComparable<T>
하고 IComparable
일반적 IComparable
으로 다른 유형의 개체를 비교할 수 있다는 인상을주지 않도록 오버로드를 숨기는 것이 더 좋습니다. 마찬가지로 일부 인터페이스는과 같이 CLS 규격이 아니므로 인터페이스를 IConvertible
명시 적으로 구현하지 않으면 CLS 규격이 필요한 언어의 최종 사용자가 개체를 사용할 수 없습니다. (BCL 구현자가 기본 요소의 IConvertible 멤버를 숨기지 않으면 매우 비참 할 것입니다. :))
또 다른 흥미로운 점은 일반적으로 그러한 구조를 사용한다는 것은 인터페이스를 명시 적으로 구현하는 구조체가 인터페이스 유형에 대한 boxing을 통해서만 호출 할 수 있다는 것을 의미합니다. 일반 제약 조건을 사용하여이 문제를 해결할 수 있습니다.
void SomeMethod<T>(T obj) where T:IConvertible
당신이 그것을 전달할 때 int를 boxing하지 않습니다.
답변
인터페이스를 명시 적으로 구현해야하는 몇 가지 추가 이유 :
이전 버전과의 호환성 : ICloneable
인터페이스가 변경되는 경우 구현하는 메서드 클래스 멤버는 메서드 서명을 변경할 필요가 없습니다.
클리너 코드 : Clone
ICloneable에서 메서드가 제거 되면 컴파일러 오류가 발생 하지만 메서드를 암시 적으로 구현하면 사용하지 않는 ‘고아’공용 메서드로 끝날 수 있습니다.
강력한 타이핑 : 예제를 통해 supercat의 이야기를 설명하기 위해 이것이 제가 선호하는 샘플 코드입니다. ICloneable
명시 적으로 구현 Clone()
하면 MyObject
인스턴스 멤버 로 직접 호출 할 때 강력한 타이핑이 허용 됩니다 .
public class MyObject : ICloneable
{
public MyObject Clone()
{
// my cloning logic;
}
object ICloneable.Clone()
{
return this.Clone();
}
}
답변
또 다른 유용한 기술은 함수의 공용 메서드 구현이 인터페이스에 지정된 것보다 더 구체적인 값을 반환하도록하는 것입니다.
예를 들어 객체는을 구현할 수 ICloneable
있지만 공개적으로 표시되는 Clone
메서드가 자체 유형을 반환하도록합니다.
마찬가지로,는 IAutomobileFactory
있을 수 있습니다 Manufacture
을 반환하는 방법을 Automobile
하지만 FordExplorerFactory
, 어떤 구현 IAutomobileFactory
, 그것있을 수 있습니다 Manufacture
방법은 반환 FordExplorer
(에서 어떤 도출을 Automobile
). 타입 캐스트 할 필요없이 a에 의해 반환 된 객체에 대한 특정 속성을 FordExplorerFactory
사용할 수 있음을 알고 있는 코드는 단지 어떤 유형이 있다는 것을 알고있는 코드 는 단순히 .FordExplorer
FordExplorerFactory
IAutomobileFactory
Automobile
답변
멤버 이름과 서명이 동일한 두 개의 인터페이스가 있지만 사용 방법에 따라 동작을 변경하려는 경우에도 유용합니다. (나는 이와 같은 코드를 작성하지 않는 것이 좋습니다) :
interface Cat
{
string Name {get;}
}
interface Dog
{
string Name{get;}
}
public class Animal : Cat, Dog
{
string Cat.Name
{
get
{
return "Cat";
}
}
string Dog.Name
{
get
{
return "Dog";
}
}
}
static void Main(string[] args)
{
Animal animal = new Animal();
Cat cat = animal; //Note the use of the same instance of Animal. All we are doing is picking which interface implementation we want to use.
Dog dog = animal;
Console.WriteLine(cat.Name); //Prints Cat
Console.WriteLine(dog.Name); //Prints Dog
}
답변
인터페이스를 명시 적으로 구현하기 위해 공용 인터페이스를 깔끔하게 유지할 수 있습니다. 즉, File
클래스가 IDisposable
명시 적으로 구현 하고 ) Close()
보다 소비자에게 더 의미가 있는 공용 메서드 를 제공 할 수 있습니다 Dispose(
.
F # 은 명시 적 인터페이스 구현 만 제공하므로 해당 기능에 액세스하려면 항상 특정 인터페이스로 캐스팅해야하므로 인터페이스를 매우 명시 적으로 (말장난없이) 사용할 수 있습니다.
답변
내부 인터페이스가 있고 클래스에서 멤버를 공개적으로 구현하지 않으려면 명시 적으로 구현합니다. 암시 적 구현은 공개되어야합니다.