如何继承方法但具有不同的返回类型?

时间:2009-11-12 16:47:50

标签: c# inheritance

鉴于以下类别:

ClassA
{
     public ClassA DoSomethingAndReturnNewObject()
     {}    
}

ClassB : ClassA
{}

ClassC : ClassA
{}

有没有办法让ClassBClassC继承方法但是将返回类型自定义为自己的类?

我不想从ClassA复制方法并在那里更改类型。

当我致电ClassB时,我需要获得ClassB.DoSomethingAndReturnNewObject()个对象。

当我致电ClassC时,我需要获得ClassC.DoSomethingAndReturnNewObject()个对象。

基于当前类型调用构造函数,例如:this.GetType()?但我不知道如何实际做到这一点。

10 个答案:

答案 0 :(得分:8)

不,您提到的功能称为return type covariance。它在C#中不受支持。

答案 1 :(得分:6)

您所描述的是covariant return type,C#不支持。

但是,您可以将ClassA创建为开放式泛型,并使封闭的泛型继承者返回自己的类型。

示例:

public abstract class ClassA<T> where T: ClassA<T>, new()
{
    public abstract T DoSomethingAndReturnNewObject();
}

public class ClassB: ClassA<ClassB>
{
    public override ClassB DoSomethingAndReturnNewObject()
    {
        //do whatever
    }
}

答案 2 :(得分:6)

您需要为要使用的DoSomethingAndReturnNewObject创建受保护的虚拟方法:

class ClassA
{
    protected virtual ClassA Create()
    {
        return new ClassA()
    }

    public ClassA DoSomethingAndReturnNewObject()
    {
        ClassA result = Create();
        // Do stuff to result
        return result;
    }
}

class ClassB : ClassA
{
     protected override ClassA Create() { return new ClassB(); }
}

class ClassC : ClassA
{
     protected override ClassA Create() { return new ClassC(); }
}

请注意,返回类型仍为ClassA,但对象实例类型将是特定类。

答案 3 :(得分:2)

class ClassA<T> where T : ClassA<T>, new()
{
    public T DoSomethingAndReturnNewObject()
    {
        return new T();
    }
}

class ClassB : ClassA<ClassB> { }

class ClassC : ClassA<ClassC> { }

测试:

ClassB b1 = new ClassB();

ClassB b2 = b1.DoSomethingAndReturnNewObject(); // returns instance of ClassB

答案 4 :(得分:0)

也许仿制药会成为你的救世主。看看这个链接: C# Generics Part 3/4: Casting, Inheritance, and Generic Methods

bstract class  B<T> {
   public abstract T Fct(T t);
}
class D1 : B<string>{
   public override string Fct( string t ) { return "hello"; }
}
class D2<T> : B<T>{
   public override T Fct(T t) { return default (T); }
}

答案 5 :(得分:0)

嗯,正确的答案是否定的,一般来说,这是一个坏主意。如果你要回到完全不同的东西,那么找另一种方式。

但是,如果您没有返回完全不同的东西,那么界面可以解决您的问题。而不是返回一个类,返回一个接口,让类A,B和C返回以他们认为合适的方式实现该接口的对象。

答案 6 :(得分:0)

这不是继承,因为方法的返回类型是其签名的一部分。你没有改变方法,你将创建一个全新的方法。

你有一些选择。例如,您可以使方法DoSomethingAndReturnNewObject成为基于泛型的方法,并让它返回其泛型类型。这可能是您正在寻找的确切行为的最直接途径。

另一种方法是按原样保留方法签名,并让子类方法返回ClassBClassC的实例。然后客户端代码需要负责转换,以便将这些对象用作适当的派生类。

ClassA的公共接口是否足够?如果您正确地派生和覆盖了虚拟成员,那么多态性将为您提供正确的功能,如果您只使用ClassA成员。

答案 7 :(得分:0)

我终于设计了以下解决方案。对于我的情况,它足够有用,但它假设ClassA知道它的衍生物并且仅限于这两个选项。不是高层思考,但它确实有效。 :)

ClassA
{
    public ClassA DoSomethingAndReturnNewObject()
    {
        if (this.GetType() == typeOf(ClassB))
        {
            return new ClassB(values);
        }
        else
        {
            return new ClassC(values):
        }
    }    
}

ClassB : ClassA
{}

ClassC : ClassA
{}

答案 8 :(得分:-1)

我认为您需要使用新的返回类型创建一个新函数并在另一个函数内部调用,并操纵返回的类型。 否则就不符合逻辑! (与继承的定义/想法)

答案 9 :(得分:-2)

有一个真正简单的答案:让所有方法返回类型“对象”。你显然会返回不同的类型,字符串和整数以及诸如此类的东西,并且它们会在到达目的地后保持原样。但编译器非常高兴 - 一切都是“对象”。你确实放弃了编译时类型检查,这不是一件好事,但每隔一段时间进行一次深度OO编程就会有回报。