Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type of child class from parent class method

Tags:

c#

inheritance

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?

like image 654
user3772515 Avatar asked Jan 16 '15 21:01

user3772515


1 Answers

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>

like image 130
David Avatar answered Nov 13 '22 07:11

David