简体   繁体   中英

Return type of child class from parent class method

If I have a class A , and classes B , C , and D that inherit from A , is there a way to write a method in A that, when called on the subclass, will have a return type of the subclass?

So if I were to do A.myMethod() , I would get an A , and if I were to do B.myMethod() , I would get an instance of B ?

What you are asking is not strictly polymorphism, since you want to override a return type, and thus have a different signature from the original method. True polymorphism changes none of this signature, so what you're asking isn't a first-class situation in C#.

That being said, there are at least two ways about it.

The simplest way is to override the method, using the new keyword to hide the original method, allowing you to change the signature.

public new B MyMethod() { return (B)(base.MyMethod()); }

This will allow any usages of B to return a B , but does not actually override the behaviour of A.MyMethod . It can be useful to avoid repetitive typecasting in code.

if you need to also override the method to allow it to return an object of type B , this cannot coexist in the same class, because the compiler sees the same signature (same name, same parameters, even though the return type is explcitly different).

The second way is called Static Polymorphism , and is very useful if you're using a factory of some kind, but can bevery tricky to work around, because it allows exactly one level of actual inheritance. A Statically Polymorphic type starts with a type that has a Generic component constrained against itself:

public class A<TSelf> where TSelf : A<TSelf> { }
public class B : A<B> { }

This means your method could return an object of type TSelf or even make this an abstract method so each inheritor has to deal with the constructor, but any class inherited from B has a harder time overriding this, since it's inheriting from A<B> , not A<C>

Assuming that you want to declare method myMethod in A only, you can do the following:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new A();
            var b = new B();

            Console.WriteLine(a.M());
            Console.WriteLine(b.M());
        }
    }

    class A
    {
        public A M()
        {
            return (A)Activator.CreateInstance(GetType());
        }
    }

    class B : A 
    {
    }
}

prints:

Test.A
Test.B 

What you are talking about is basically a Factory method/pattern. Its a little off because instances creating themselves is just weird.

But sure, you can write this:

class A
{
   public virtual A Create()
   {
      return new A();
   }
}

class B
{
   public override A Create()
   {
       return new B();
   }
}

Of course, the return type has to stay as the base class, but since you are taking advantage of polymorphism, that shouldn't be a problem.

Normally the factory method would be in another purpose-built class, just so you know.

Yes and No. Consider:

public class Parent
    {
        public int MyProperty { get; set; }

        public virtual Parent MyMethod()
        {
            return new Parent();
        }
    }

    public class A : Parent
    {
        public override Parent MyMethod()
        {
            return new A();
        }
    }

In A, although the return type is Parent, you are returning an A.

If you asking about compile time no you can't write override methods with different return types.

But on run time yes you can and you will have those type of instances but you have to write your code so as to have a return type of 'A' and then cast them to wanted type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM