【问题标题】:casting to base interface implementation of reimplemented interface转换为重新实现接口的基本接口实现
【发布时间】:2015-02-18 19:23:10
【问题描述】:

我有一个由类Animal 实现的接口IFace。我无法修改IFace 或Animal。我想用我的子类Human 扩展Animal 并让它重新实现IFace。但是,我希望能够将Human 的实例存储在IFace 类型的变量中,这样访问该变量就可以直接使用Animal 实现——就好像变量的类型是Animal。

https://dotnetfiddle.net/6JjNfR

using System;

interface IFace
{
    void Talk();
}
class Animal : IFace
{
    public void Talk()
    {
        Console.WriteLine("Oink");
    }
}
class Human : Animal, IFace
{
    public new void Talk()
    {
        Console.WriteLine("Hi");
    }
}

public class Program
{
    public static void Main()
    {
        var human = new Human();
        human.Talk();

        var face = (IFace)human;
        face.Talk();

        var animal = (Animal)human;
        animal.Talk();

        var face2 = animal;
        face2.Talk();

        IFace face3;
        face3 = human;
        face3.Talk();

        // How to get the following to oink like animal?
        face3 = animal;
        face3.Talk();
    }
}

这可能吗,还是我必须创建一个如下所示的代理类?

https://dotnetfiddle.net/marXND

class AnimalProxy : IFace
{
    Animal Animal { get; set; }

    public AnimalProxy(Animal animal)
    {
        Animal = animal;
    }

    public void Talk()
    {
        Animal.Talk();
    }
}

如果需要代理,如果我可以通过转换为Animal 来访问IFace 的Animal 实现,为什么还需要代理?

我敢打赌,答案与显式接口的工作原理以及如何将Human 转换为Animal 然后再次转换为IFace 相关应该返回Human实现……也许隐式接口实现语法只是让 C# 编译器自动生成一个显式实现,它只调用隐式实现。这意味着当我将某些内容转换为 Animal 时,我访问的是 Animal 方法而不是 IFace 方法,即使这些相同的方法是 IFace 的“隐式”实现。

那么,我如何才能直接转换为重新实现的接口的基本实现?如果不可能,为什么?

【问题讨论】:

  • 我觉得有义务指出,想要这样做的想法表明你的类型设计存在严重错误,无论是否可能,你都应该 强烈考虑重新设计你的类型系统。
  • 我很害怕,但还是 ;-)。

标签: c# interface casting


【解决方案1】:

不要让Human定义重新实现接口:

class Human : Animal // , IFace
{
    public new void Talk()
    {
        Console.WriteLine("Hi");
    }
}

如果你这样做,在 Human 上调用 Talk 将使用新的实现,但在 IFace 上调用 Talk 恰好是 Human 将使用基类的实现。

请参阅this article 了解更多信息,甚至更奇怪的情况,围绕界面重新实现。

【讨论】:

  • 但我也希望能够以IFace 的身份传递Human。我总是可以让代理类包装 Human 而不是 Animal,但这不是我认为的重点。
  • @binki 您可以将Human 作为IFace 传递。如果你这样做了,并且不重新实现接口,它将具有基类为接口定义的行为。
  • 但是我希望能够将 Human 传递为 IFace 已经覆盖了接口实现而不能够 override 它......请参阅问题:“我想扩展 Animal使用我的子类 Human 并让它重新实现 IFace。”
  • @binki 然后你需要Human 来重新实现接口,这样任何Human 类型为IFace 的实例都将使用新的实现。您可以拥有一个或另一个,但您不能让 some Human 实例重新实现接口,而有些则没有。要么重新实现它,要么不重新实现。
  • 当然可以,但是如果我可以通过转换为Animal 来访问基本实现,为什么不能获得我想要的行为?我不应该能够做类似IFace thing = (IFace)(Animal)human; 的事情吗?
猜你喜欢
  • 2019-07-26
  • 1970-01-01
  • 2014-06-17
  • 2016-07-22
  • 1970-01-01
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多