And*_*erd 13
另一方面:
如果隐式实现,则意味着类的用户可以访问接口成员,而无需对其进行强制转换.
如果明确实现,客户端必须先将类转换为接口,然后才能访问成员.以下是显式实现的示例:
interface Animal
{
void EatRoots();
void EatLeaves();
}
interface Animal2
{
void Sleep();
}
class Wombat : Animal, Animal2
{
// Implicit implementation of Animal2
public void Sleep()
{
}
// Explicit implementation of Animal
void Animal.EatRoots()
{
}
void Animal.EatLeaves()
{
}
}
Run Code Online (Sandbox Code Playgroud)
您的客户代码
Wombat w = new Wombat();
w.Sleep();
w.EatRoots(); // This will cause a compiler error because it's explicitly implemented
((Animal)w).EatRoots(); // This will compile
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 10
IDE为您提供了选择 - 两种方法都不常见.通过显式实现,成员不在(主)公共API上; 如果接口没有直接绑定到对象的意图,这是很方便的.例如,ICustomTypeDescriptor成员对常规调用者并不是那么有用 - 只对某些非常具体的代码有用,因此没有任何目的在公共API上使用它们导致混乱.
这在以下情况下也很有用:
Foo方法和您自己的类型的Foo方法之间存在冲突,它们意味着不同的东西最后一点的典型示例是IEnumerable<T>,GetEnumerator()在接口层次结构中有两个级别的方法 - 通常IEnumerator<T>使用隐式实现实现typed()版本,IEnumerator使用显式实现实现untyped()版本.
这是普通英语的不同之处:
假设你有一个接口Machine,它有一个函数Run(),另一个接口Animal也有一个函数调用Run().当然,当一台机器运行时,我们正在谈论它的启动,但是当一只动物跑来跑去时,我们正在谈论它的移动.那么当你有一个对象时会发生什么,让我们称它为Aiboa Machine和a Animal?(顺便说一句,Aibo是一只机械狗.)Aibo跑步时,他是开始跑步还是四处移动?明确地实现接口可以让您做出区分:
interface Animal
{
void Run();
}
interface Machine
{
void Run();
}
class Aibo : Animal, Machine
{
void Animal.Run()
{
System.Console.WriteLine("Aibo goes for a run.");
}
void Machine.Run()
{
System.Console.WriteLine("Aibo starting up.");
}
}
class Program
{
static void Main(string[] args)
{
Aibo a = new Aibo();
((Machine)a).Run();
((Animal)a).Run();
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是我不能简单地调用a.Run()因为我的函数实现都明确地附加到接口.这是有道理的,因为否则编译器将如何知道要调用哪一个?相反,如果我想直接调用Run()我的函数Aibo,我还必须在没有显式接口的情况下实现该函数.