user3593478 user3593478 - 2 months ago 12
C# Question

Hidden Inherritance c#

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
.

Answer
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).

Comments