I have a base class (A
) and a delivered one (B
). They inherit the ICloneable<>
generic interface that I made:
interface ICloneable<T>
{
T Clone();
}
I would like to override the A.Clone()
method in B
but so, that B.Clone()
returns an object of type B
instead of A
, however, overriding does not allow that.
I have some kind of workaround, but I find it really ugly:
class A : ICloneable<A>
{
virtual A Clone() => /*magic*/;
}
class B : A, ICloneable<B>
{
B CloneAsB() => /*other kind of magic*/;
override A Clone() => CloneAsB();
}
(I also added explicit implementation of the non-generic ICloneable
, but did not show it in the example.)
Is there a better way to achieve this, without having to have a false clone method?
I found a better workaround: passing the call of the generic ICloneable<A>.Clone()
method down the inheritance hierarchy using the non-generic ICloneable.Clone()
might be useful, as shown here:
class A : ICloneable<A>, ICloneable
{
A Clone() => (A) ((ICloneable) this).Clone(); //This will call ICloneable.Clone in class B if the type of the object is B!
//If object is of type B, not this but the derived method is called:
object ICloneable.Clone() => /*Cloning, if object is an instance of A*/;
}
class B : A, ICloneable<B>
{
new B Clone() => (B) ((ICloneable) this).Clone(); //This will call ICloneable.Clone in a derived type if object is of more derived type!
//If object is of even more derived type, not this but the method of the derived class is called:
object ICloneable.Clone() => /*Cloning, if object is an instance of B*/;
}
//Same implementation for class C...
This has the advantage that none of the methods have to explicitly check for the type of the object (i.e. in class A
, Clone()
does not have to check if the object is of type B
).