【问题标题】:Overriding (shadowing, overloading?) methods with different return types in a C# hierarchy在 C# 层次结构中使用不同的返回类型覆盖(遮蔽、重载?)方法
【发布时间】:2013-12-21 01:00:37
【问题描述】:

我正在编写一个 SDK,它具有用于实现数据类型的 OOP 结构;

  1. 首先是一个界面
  2. 然后是抽象实现
  3. 终于有了抽象的通用实现

人们可以选择实现接口,或者从任一类派生。

public interface IGoo
{
  IGoo Duplicate();
  ...
}
public abstract class Goo : IGoo
{
  IGoo IGoo.Duplicate() {
    return Duplicate();
  }
  abstract public Goo Duplicate();
  ...
}
public abstract class Goo<T> : Goo
{
  abstract public Goo<T> Duplicate(); ??????
  ...
} 

我想重新实现 Duplicate 方法,以便它始终返回可能的最具体的类型。 IE。当你在一个 IGoo 实例上调用 Duplicate 时,你会得到另一个 IGoo。如果你在 Goo 上调用它,你会得到 Goo,如果你在 -say- Goo 上调用它,你会得到 Goo。而且所有 Duplicate() 方法总是调用最具体的实现。

这可能吗?只有当您可以显式实现接口时才有可能?在这种情况下,我不应该让 Goo 从 Goo 派生,而是让它实现 IGoo 并将所有低级功能键入两次?

【问题讨论】:

  • 抱歉,我在给出第一个答案时忽略了这个细节,哈哈。下面使用 System.Object 作为返回值的答案呢?它对类型匹配保持友好。
  • 嗯,返回对象比返回 IGoo 还要糟糕。我知道这只是语法糖,但如果可能的话,我想避免任何强制转换。从 Goo 和 Goo 实现 IGoo 接口似乎是最好的解决方案,即使这确实意味着我必须在两个类中维护一堆相同的代码。

标签: c# oop overriding overloading shadowing


【解决方案1】:

接下来呢?

public interface IObj
{
    IObj Duplicate();
}

public abstract class Obj : IObj
{
    public Obj()
    {

    }
    public virtual IObj Duplicate()
    {
        return this;
    }
}

public abstract class ObjT<T> : Obj
{
    public ObjT()
    {

    }
    public override IObj Duplicate()
    {
        return this;
    }
}

public class ObjImpl : Obj
{

}

public class ObjTImpl : ObjT<int>
{

}

我知道您希望它在任何继承类中返回最具体的类型,但实际上是这样。它将继承类型装箱到接口中(或者如果您在哪里返回对象而不是接口类型,则为原始对象。如果您在控制台应用程序中运行以下测试,您将看到表示正确的类型:

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            ObjImpl a = new ObjImpl();

            ObjTImpl b = new ObjTImpl();

            Console.WriteLine(a.Duplicate().GetType());
            Console.WriteLine(b.Duplicate().GetType());

            Console.ReadLine();
        }
    }
}

// outputs:

// ObjImpl
// ObjTImpl

重新定义抽象的抽象的想法与抽象多态的目的背道而驰。如果派生类型不打算实现继承的抽象成员,则不应继承它。

虽然我上面给出的示例需要强制转换才能访问任何特定于子类的成员,但这将是在这种方法中执行此操作的正确方法。运行时需要知道它应该处理什么类型。

总有你可以玩弄的动态,但老实说,我没有玩过泛型和继承的动态,因为我怀疑我会让我的编译器哭泣,当它哭泣时,我哭泣,有点深在里面......大声笑

【讨论】:

    【解决方案2】:

    只有在显式实现接口时才有可能。这是因为方法的返回类型不是其签名的一部分——编译器在重载时会检查它。因此,其他仅返回类型不同的相同方法在语法上是不可能的。

    【讨论】:

    • 我担心托马斯。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多