In c#, is it possible to prevent the programmer to inherit a parent class, but allow child classes to be inherited from (perhaps just during the writing of the code, not during runtime)?
For example:
//Class which should only allow 'RangedAbility' and 'MeleeAbility' to inherit.
//No other classes are to be allowed to inherit from Ability
public abstract class Ability{
public virtual void foo(){}
}
public class RangedAbility : Ability{
//an empty class
}
public class MeleeAbility : Ability{
//an empty class
}
public class myAbility : MeleeAbility{
public override void foo(){ /*some code*/}
}
//attempting to inherit from `Ability` instead of `MeleeAbility` or instead of 'RangedAbility'
//should result in programmer facing an error in IDE such as Visual Studio.
Using "sealed" on Ability
will not work (it is abstract, as well as RangedAbility
, MeleeAbility
need to inherit from it).
Reflection approach to "simmulate" inheritance by those two child classes would be very tedious and had to be done in both MeleeAbility
and RangedAbility
.
Abandoning the use of Ability
completely, and forcing RangedAbility
and MeleeAbility
to implement an interface doesn't seem like a good option either, because they share methods that would be better-off written once through a "hidden" parent class.
The reason for doing such code is that I need to determine at runtime what kind of behavior to expect from 'myAbility' type. It is done through IsSubclassOf(typeof(MeleeAbility))
or IsSubclassOf(typeof(RangedAbility))
, which allows to determine expected behavior without needing an actual instance of myAbility
.
public abstract class Ability
{
internal Ability()
{
}
public virtual void foo(){}
}
Because the only constructor for Ability
is internal
only a derived class from within the same assembly can be constructed (constructors that don't explicitly build on a base constructor are implicitly : base()
). Any attempt for a class in another assembly to derive directly from Ability
will not have a valid constructor.
(On a related note, you might find an internal abstract property that your own classes override to return different values as neater method of determining which you have than doing explicit IsSubClassOf
or even is
tests. Or better again, providing whatever functionality turns on such a test through an internal abstract method).