Is there some way to define an abstract type as a parameter in an abstract method, and when that method is implemented in a derived class, you change the type of the method to accept a derived type?
Code:
public abstract class ProductBase
{
}
public class SomeProduct
: ProductBase
{
}
public abstract class A
{
protected abstract void addProduct(ProductBase p);
}
// This works
public class B : A
{
protected override void addProduct(ProductBase p)
{
// Do some work
}
}
// This is what I'd like to do
public class C : A
{
// Compiler error here because I have accepted a SomeProduct and not a ProductBase
protected override void addProduct(SomeProduct p)
{
// Do some work on the specialisation - I can use the SomeProduct directly
}
}
In my head, it makes some kind of sense. An abstract class indicating there is a method which derived classes must implement, but they can change the type of object passed in as a parameter, so long as it is from the same inheritance chain...
What I have ended up doing, is to remove the abstract method AddProduct
from the abstract class, and instead just implementing it in the derived class anyway, but there's then no contract for other classes in the future that they must create their own implementation of AddProduct
. And it doesn't feel right.
I hope this makes sense. Apologies if this is a duplicate question but I couldn't find anything by searching.
Thanks,
bgs264
You can make your
A
class to generic and use the generic argument in youraddProduct
method:No, that is not possible: Assume you are calling
addProduct
on a variable of classA
that points to an instance of classC
, passing an object that is aProductBase
, but not aSomeProduct
. The passed instance could not be converted toSomeProduct
, which is why this will not compile in the first place.The closest thing to this is a solution with generics:
Then, you can define your class C like so:
Of course, that means you have to type any variables of type
A
toSomeProduct
, as inA<SomeProduct> = new C();
.You cannot have just a variable of type
A
(that provides anaddProduct
method) any more without specifying the actual value of theT
type argument. On the other hand, calling thataddProduct
method would not have been possible in your solution, either, as outlined above.You might introduce a non-strongly-typed method now:
However, such a solution is usually really only required when there are some users of the class that can know the generic type while others don't.
Frankly, for implementation code I'd just live with a cast. The only time I'd make this "pretty" is if it impacted public callers:
One option, that I don't like much myself, is generics:
The reason I don't like this is that you can't just use the non-generic
A
anymore, so you lose a lot of abstraction. Another option is tonew
the method to re-declare the parameters. Unfortunately, you can'tnew
andoverride
at the same level, but a workaround is to use 2 methods: