How to make the constructor available only to the base class?

If I need a constructor accessible only from child classes, I can use the protected keyword in the constructor.

Now I want the opposite.

My child class must have a constructor that its base class can access, but not from any other class.

Is it possible?

This is my current code. the problem is that child classes have an open constructor.

 public abstract class BaseClass { public static BaseClass CreateInstance(DataTable dataTable) { return new Child1(dataTable); } public static BaseClass CreateInstance(DataSet dataSet) { return new Child2(dataSet); } } public class Child1 : BaseClass { public Child1(DataTable dataTable) { } } public class Child2 : BaseClass { public Child2(DataSet dataSet) { } } 
+6
source share
5 answers

I think you have two options:

  • Make child constructor internal . This means that it will be available from all types in the same assembly, but in most cases this should be enough.
  • Make the child classes nested in the base class:

     public abstract class BaseClass { public static BaseClass CreateInstance(DataTable dataTable) { return new Child1(dataTable); } private Child1 : BaseClass { public Child1(DataTable dataTable) { } } } 

    Thus, BaseClass can use the constructor, but no other external type can do this (or even see a child class).

+12
source

The answer to the question: "NO"

There is no such thing in OOP that allows the constructor of child classes to see only the base class ...

+3
source

I think I just decided it myself. After reading the svicks solution with nested classes, I thought why not use an protected nested class as an argument?

No one from outside can create an Arg instance, and public contructors from my child classes can use BaseClass, which can create Arg<T> instances.

 public abstract class BaseClass { protected class Arg<T> { public T Value { get; set; } public Arg(T value) { this.Value = value; } } public static BaseClass CreateInstance(DataTable dataTable) { return new Child1(new Arg<DataTable>(dataTable)); } public static BaseClass CreateInstance(DataSet dataSet) { return new Child2(new Arg<DataSet>(dataSet)); } } public class Child1 : BaseClass { public Child1(Arg<DataTable> arg) : this(arg.Value) { } private Child1(DataTable dataTable) { } } public class Child2 : BaseClass { public Child2(Arg<DataSet> arg) : this(arg.Value) { } public Child2(DataSet dataSet) { } } 
+3
source

One could provide the desired runtime behavior if the base constructor accepts the ref parameter and does something like (not thread safe):

 private int myMagicCounter; public DerivedClass makeDerived(whatever) // A factory method { DerivedClass newThing; try { ... do whatever preparation newThing = new DerivedClass(ref myMagicCounter, whatever); } finally { ... do whatever cleanup } return newThing; } BaseClass(ref int magicCounter, whatever...) { if (magicCounter != myMagicCounter) throw new InvalidOperationException(); myMagicCounter++; if (magicCounter != myMagicCounter) throw new InvalidOperationException(); } 

Note that to call the constructor of a derived class, it is impossible to gain control without executing the factory method or return control to its caller without clearing the factory method. However, there will be nothing to prevent the constructor of the derived class from passing its partially constructed instance to the external code, which can do whatever it likes with it for an arbitrary amount of time before returning control to the factory method.

0
source

As Pranai Rana said, this is not possible. If you can clearly explain why you want this and why there is no other technique, maybe Microsoft C # designteam will want to add this to a future version of C #.

However, C # (and many other OO languages ​​have been around for many years without this feature.

-1
source

Source: https://habr.com/ru/post/916562/


All Articles