“显式实现接口”和“实现接口”的区别是什么?
当您从接口派生一个类时,智能感知会建议您两者都进行。
但是,它们之间有什么不同呢?
这方面的另一个方面是:
如果你实现了隐式接口,这意味着接口成员对于你类的用户是可访问的,而无需进行强制类型转换。
如果它被显式实现,客户端在访问成员之前必须将你的类转换为接口。以下是显式实现的示例:
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()
{
}
}
您的客户端代码
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
IDE提供了两种选择,不会同时使用。采用显式实现时,成员不在(主要的)公共API上;如果接口与对象本身的意图没有直接联系,则这非常方便。例如,ICustomTypeDescriptor成员对于常规调用者来说并不是特别有用,只有一些非常具体的代码才需要它们,因此没有把它们放在公共API上会更加清晰。
如果满足以下条件,也会很有用:
Foo
方法和您自己类型的Foo
方法之间存在冲突,并且它们表示不同的含义最后一点的典型例子是IEnumerable<T>,它在接口层次结构中有两个级别的GetEnumerator()方法-通常使用隐式实现实现类型化(IEnumerator<T>
)版本,使用显式实现实现未经过类型化的(IEnumerator
)版本。
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();
}
}
这里的问题在于,我不能简单地调用 a.Run()
,因为我实现的两个函数都明确附加在一个接口上。这很有道理,否则编译器怎么知道该调用哪一个呢?相反,如果我想直接在 Aibo
上调用 Run()
函数,我还需要 额外 实现一个没有明确接口的函数。
明确实现puts函数名的完全限定名称,请考虑以下代码
public interface IamSam
{
int foo();
void bar();
}
public class SamExplicit : IamSam
{
#region IamSam Members
int IamSam.foo()
{
return 0;
}
void IamSam.bar()
{
}
string foo()
{
return "";
}
#endregion
}
public class Sam : IamSam
{
#region IamSam Members
public int foo()
{
return 0;
}
public void bar()
{
}
#endregion
}
IamSam var1;
var1.foo() returns an int.
SamExplicit var2;
var2.foo() returns a string.
(var2 as IamSam).foo() returns an int.
不同的是您可以从多个接口继承类。 这些接口可能具有相同的方法签名。 显式实现允许您根据用于调用它的接口更改实现。
显式接口实现是指除非你明确转换,否则实现将被隐藏,当接口与类功能正交时,这种实现最为有用。也就是说,行为上不相关。
例如,如果你的类是Person,而接口是ISerializable,那么通过Intellisense看到一个奇怪的名为“GetObjectData”的东西对于处理Person属性的人来说并没有太多意义。因此,你可能希望明确地实现该接口。
另一方面,如果你的Person类恰好实现了IAddress,那么在Person实例上直接看到AddressLine1、ZipCode等成员是完全合理的(隐式实现)。