gpt4 book ai didi

c# - 为什么在实现接口(interface)方法时允许虚拟?

转载 作者:可可西里 更新时间:2023-11-01 08:00:03 27 4
gpt4 key购买 nike

我对接口(interface)有一个特定的查询。

默认情况下,接口(interface)方法是抽象的和虚拟的,所以如果我们实现该接口(interface)并在类中给出定义,我们实际上会重写该方法,但是当我们在实现类中再次将方法标记为虚拟时,为什么编译器不考虑我们实际上是想隐藏原来的接口(interface)虚方法。

如果我们在基类中有一个虚方法并且派生类再次将该方法标记为虚方法,在这种情况下编译器会警告您隐藏了基类方法,因此如果您有意隐藏基类方法,请使用 new .

public interface ITestInterface
{
void virtualmethod(); // this method is by default virtual.
}
public class TestInterface :ITestInterface
{
public virtual void virtualmethod()
{
// Now compiler should consider that i am actually hiding the interface virtual method.
}
}

如果您为界面构建上述代码并在 ILDASM 中打开,您将看到如下代码:

.method public hidebysig newslot abstract virtual
instance void virtualmethod() cil managed
{
}//end of method ITestInterface::virtualmethod

最佳答案

默认情况下,从接口(interface)实现的方法不是虚拟的。您只是提供接口(interface)定义中定义的契约的实现。通过将方法标记为 virtual,您允许派生类提供额外的或单独的实现,同时仍然遵守定义的契约。

考虑这个例子:

interface IAnimal
{
string Speak();
}

class Dog : IAnimal
{
public string Speak()
{
return "Bark!";
}
}

Dog 类通过提供契约 IAnimal 的实现来实现 接口(interface)。这里没有虚拟方法,也没有覆盖。

现在考虑这个例子:

interface IAnimal
{
string Speak();
}

class Dog : IAnimal
{
public virtual string Speak()
{
return "Bark!";
}
}

class GoldenRetriever : Dog
{
public override string Speak()
{
return "I am a golden retriever who says "
+ base.Speak();
}
}

现在 Dog 类已将 Speak 声明为 virtual,这允许派生类提供额外的或新的实现。这不会违反与 IAnimal 的约定,因为对 Speak 方法的任何调用仍会返回一个字符串。

好的,最后一个例子。请记住,接口(interface)不需要实现——它们只需要满足契约。这意味着接口(interface)只关心成员是否存在于具有匹配签名的实现类中。这意味着我们也可以这样做:

interface IAnimal
{
string Speak();
}

abstract class Dog : IAnimal
{
public abstract string Speak();
}

class GoldenRetriever : Dog
{
public override string Speak()
{
return "I am a golden retriever";
}
}

现在请注意,Dog 类根本没有为 Speak 提供实现,但已满足契约的要求。

接口(interface)也从一个类继承到另一个类,因此在上面的所有示例中,DogGoldenRetriever 都实现了 IAnimal 接口(interface)。两个类都隐藏 Speak 方法 - 两个类都实现它。


好的,我认为您的困惑可能来自于虚方法是在接口(interface)中定义的,而不是在类中定义的。这是我在上面定义的接口(interface)的 IL:

.class private interface abstract auto ansi IAnimal
{
.method public hidebysig newslot abstract
virtual instance string Speak() cil managed
{
}
}

虽然您将方法定义为 virtual 是正确的,但您还需要注意此处的类型被指定为 interface。这纯粹是 Microsoft 的 C# 编译器生成的 MSIL 的实现细节——另一个编译器可以轻松生成不同的代码,只要它在语义上提供相同的结果。

这里重要的是:即使该方法在接口(interface)中声明为 virtual 并不意味着它与声明的 virtual 方法相同在类里面。

关于c# - 为什么在实现接口(interface)方法时允许虚拟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4470446/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com