【问题标题】:How to call the base interface implementation when derived classes re-implement the interface?派生类重新实现接口时如何调用基接口实现?
【发布时间】:2014-06-17 01:59:46
【问题描述】:

因此,出于某种原因,我正在测试 C# 和 .NET VM 的限制。我遇到了一些令人困惑的行为。

采用这些类和接口:

public interface ITest
{
    void Test();
    void Test2();
}
public abstract class Base : ITest
{
    void ITest.Test()
    {
        Console.WriteLine("base");
    }
    public void Test2()
    {
        Console.WriteLine("base2");
    }
    public void Test3()
    {
        Console.WriteLine("base3");
    }
}
public class Impl : Base, ITest
{
    void ITest.Test()
    {
        Console.WriteLine("impl");
    }
    void ITest.Test2()
    {
        Console.WriteLine("impl2");
    }
    public void Test3()
    {
        Console.WriteLine("impl3");
    }
}

然后像这样使用它们:

        var i = new Impl();
        var b = (Base)i;
        var itest1 = (ITest)i;
        var itest2 = (ITest)b;
        itest1.Test();
        itest2.Test();
        itest1.Test2();
        itest2.Test2();
        i.Test2();
        b.Test2();
        i.Test3(); //for reference, a standard non-virtual method outside of an interface
        b.Test3();

我希望输出看起来像这样:

impl
base
impl2
base2
impl2
base2
impl3
base3

当然,事情不可能这么简单。所以,实际的输出是这样的:

impl
impl
impl2
impl2
base2
base2
impl3
base3

除了这种疯狂的怪异行为之外,是否可以访问 Base.Test() 实现?

【问题讨论】:

  • 尽我所能。投射没有转换。
  • 准确地说,转换不是转换。此外,我建议稍微重命名问题:派生类显式重新实现接口时如何调用基接口显式实现?

标签: c# .net inheritance interface


【解决方案1】:

也许您应该检查一下为什么您会发现结果很奇怪。对我来说,看起来你得到了你所实施的东西。

没有办法得到Base.Test,因为没有Base.Test。您需要通过接口显式访问它,然后它不再是Base,而是Impl,因为底层的真实对象不是Base类型。

【讨论】:

  • 但是,如果您将 Test3 方法添加到 Base 和 Impl,而不是添加到接口,那么您会看到我期望的 base3、impl3 行为
  • 它似乎将接口实现视为始终是虚拟的,但它们并未标记为虚拟。如果一切都是虚拟的,我会期待这种行为
  • 这里的关键是你在Impl中重新实现了接口。因此它将使用其本机实现而不是从 Base 继承的实现。
  • @NickZimmerman 但是怎么做?它被强制转换为 Base,那为什么不使用 Base 的实现呢?
  • 请注意,当您不强制转换为 ITest 时,您将获得 Base 实现,因为它通过继承链,采用继承的版本。
【解决方案2】:

Base 明确实现了ITest.Test()。这是一个实现,但它是一个“私有”实现,只能通过ITest 接口访问。

最重要的是,Impl 正在重新实现 ITest.Test(),因此当您尝试您的itest2.Test() 时,您稍后会指出这一点重新实现强>。

这里有两个关键点:

  1. 没有公开的Base.Test()
  2. 通过在Impl重新实现它,你扼杀了访问Base 上的ITest.Test() 实现的所有可能性。

重新实施,重新实施,重新实施。

我可以建议稍微重命名这个问题:派生类显式重新实现接口时如何调用基接口显式实现?因为这就是你要问的......

【讨论】:

    猜你喜欢
    • 2013-09-30
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 2016-07-22
    相关资源
    最近更新 更多