Xenoprimate
Xenoprimate

Reputation: 7963

Control Instantiation of objects without restricting constructor access

When we want to control instantiation of objects, we often make the constructor private or internal:

public class A {
    private A(int aParam) { }
}

However, this is essentially the same as sealing the class 'A' because now no one can inherit from it.

So, we can make the constructor protected:

public class A {
    protected A(int aParam) { }
}
public class B {
    protected B(int aParam) : base(aParam) { }
}

However, this means that any code from B (or any class derived from it) can instantiate a new A.

I am looking for a way to control instantiation but without having to make classes sealed (effectively or otherwise).

Note: I know that classes can always be instantiated with reflection and other tricks anyway; I'm only interested in creating an explicit 'contract'. If someone wants to subvert my contract deliberately that's up to them.

Upvotes: 3

Views: 577

Answers (3)

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73442

Am not sure what you mean. If am not wrong then you're trying to prevent instantiation of Base Class from Derived Class Right?

That is the default behavior too. You cannot instantiate base class from derived class when your base class constructor is protected.

class Program
{
    A a = A.CreateInstance();//works
    B b = B.CreateInstanceOfB();//works
    A ab = B.CreateInstanceOfA();//wont work
}

public class A
{
    protected A()
    {

    }
    public static A CreateInstance()
    {
        return new A();
    }
}

public class B : A
{
    protected B()
        : base()//
    {

    }
    public static B CreateInstanceOfB()
    {
        return new B();
    }
    public static A CreateInstanceOfA()
    {
        return new A();//This wont compile CS1540: Cannot access protected member...
    }
}

Protected constructor is intended to invoke through constructor chaining(using base keyword) only. You can't instantiate it without reflection.

Hope this helps.

Upvotes: 1

BartoszKP
BartoszKP

Reputation: 35891

If you want to be able to instantiate subclasses, but prohibit explicit instantiation of a base class, then you have two options:

  • Add a pure virtual method thus making the base class abstract.

  • Add a protected constructor, and overload the "new" operator to disallow explicit instantiation of the base class, even though it's not abstract.

Upvotes: 0

Reed Copsey
Reed Copsey

Reputation: 564383

I am looking for a way to control instantiation but without having to make classes sealed (effectively or otherwise).

This is really contradictory in your requirements.

If you want to allow subclasses to be created, you must allow the subclass to effectively create the parent, which means you need to have, at a minimum, one protected constructor. Without this, there would be no way for the subclass to initialize the instance properly.

By exposing a constructor as protected, you allow subclasses to change the instantiation rules (they can always add a public constructor).

There are really only two options here:

  1. Make the constructor protected, and assume that the subclass will do the "right thing" (whatever that is in your scenario), or
  2. Seal your class, and then expose the construction method you choose. This prevents subclasses, but does not prevent your class from being reused via composition instead of inheritance.

Upvotes: 7

Related Questions