Best practice constructor with parameters in inherited classes - c#

I have following easy class design, where myObject is importing for BaseClass.
public abstract class BaseClass
{
public BaseClass(myObject parameter)
{
// ...
}
}
public class ChildClass : BaseClass
{
}
My problem is now, that I want to make my program extensible by inheriting from public BaseClass. So you could create a constructor
public ChildClass() :base(new myObject()){...}
which will lead to failures. Is there a possibilty to prevent inherited classes with own constructors? I actually would like to avoid constructors for ChildClass at all. Is this possible? Then I could use a factory and provide an Initialize method. Or is this something impossible, where I simply must be aware of and check in my code=

Classes are completely responsible for their own constructors. They aren't inherited, and every class must have a constructor. So no, there's nothing you can do to "control" what constructors a base class can or can't have.

Related

ImportingConstructors & Subclasses

I have an abstract base class, and a derived class. I'm trying to use MEF to inject a reference to to my WindowManager, by using [ImportingConstructor], in the base class.
ie.
[ImportingConstructor]
public SomeViewModel(IWindowManager windowmanager) {...}
The issue is that before I added this, all I had was no param constructors, and the derived class is complaning about If I add a no param constructor to the base class, the WindowManager never gets injected.
Using my currently limited knowledge the only way I can think of is to change the manager import to a Property Import, and just have a no param default constructor. This kind of bugs me, as the general rule seems to prefer constructor injection for required dependencies, and property injection for optional ones.
I could add overriding [ImportingConstructor]s in my subclasses, but that seems like unnecessary duplication of code.
Is there a nicer way to do this, ie making sure my dependencies are getting injected in when the derived classes are created?
Ignore MEF for a moment and consider this:
public abstract class BaseClass {
protected BaseClass(IService service) { }
}
public class SubClass : BaseClass {
public SubClass(IService service) : base(service) { }
}
Because the base class defines a single constructor, the subclass must initialise the base class, by providing an argument for the base class' constructor.
Now, with MEF, what I think you are trying to do is this:
public abstract class BaseClass {
[ImportingConstructor]
protected BaseClass(IService service) { }
}
[Export]
public class SubClass : BaseClass {
public SubClass() { }
}
It sounds like you are trying to inject something into the constructor of the base class, but you can't do that, because its the resposibility of the subclass to ensure the appropriate arguments are passed to the base class of the constructor. You need to make a modification to your subclass:
[Export]
public class SubClass : BaseClass {
[ImportingConstructor]
public SubClass(IService service) : base(service) { }
}
Now the subclass will have the service injected and will pass it to the base class.
In terms of using Property Injection vs Constructor Injection: it is preferable to initialise a type into a usable state. That being any explicit dependencies should be required in the constructor. But, because MEF will satisfy all imports, by the time you've got your part back from the container, both constructor and property injections would have already occurred, so you could potentially use property imports instead. My preference has always been to go with constructor imports.

c# Factory Method and protection levels problem

I have a base class and several subclasses derived from that base class. I also have a static function in the base class that takes some parameters, and instantiates and returns an appropriate subclass based on input parameters ( my factory method.)
Now here's my problem: I want to ONLY allow instantiation of the subclasses FROM the factory method. But if I set the constructors of the subclasses to be protected, the base class can't see them. Is there an access modifier I'm missing that would allow the base class to call the subclasses constructors, but not not allow any other classes to call them?
Internal doesn't look like it will work either...I want to limit access to the subclass constructors to just the base class, there are other classes in the same assembly that should be able to access the base factory method and but not directly instantiate any of the subclasses.
Hopefully there's something really simple I'm missing...
Example:
public class Base
{
public Base CreateChild(string childType)
{
if(childType == "A")
return new ChildA();
if(childType == "B")
return new ChildB();
return null;
}
}
public class ChildA
{
protected ChildA() // This doesn't work, since now base class can't call this!
{
}
}
public class ChildB
{
protected ChildB()
{
}
}
You can declare the child classes as private nested classes inside Base
Have you tried declaring the child classes within the base class?
public class Base {
protected class ChildA {}
protected class ChildB {}
}
If accessing any derived object through the base type is a valid scenario (let's say derived types only override base implementations and do not add new functionality) then the proposed solution of making the derived types nested private classes (as previous answers propose) is the best solution.
If that's not the case then I think you are falling into a case of unjustified complexity. What is the reason why code from your same assembly can not access ChildA and ChildB constructors? It is after all code you can control, so you can always choose to make / enforce via code review that he initalization is through the factory method.
I understand there is valid reasons to not let external assemblies freely instantiate objects except through a tightly controlled mechanism. In this case just marking the constructors as internal would do.
Otherwise, I'm not sure you can achieve what you are pretending without creating a specific assembly just for this base class and its derived classes. There is definitely no access modifier that would make a static method in a derived class only visible from it's base class.

Constructor of an abstract class in C#

Why is it possible to write constructor for an abstract class in C#?
As far as I know we can't instantiate an abstract class.. so what is it for?
You can't instantiate the class, right?
Because there might be a standard way you want to instantiate data in the abstract class. That way you can have classes that inherit from that class call the base constructor.
public abstract class A{
private string data;
protected A(string myString){
data = myString;
}
}
public class B : A {
B(string myString) : base(myString){}
}
Far as I know we can't instantiate an abstract class
There's your error right there. Of course you can instantiate an abstract class.
abstract class Animal {}
class Giraffe : Animal {}
...
Animal animal = new Giraffe();
There's an instance of Animal right there. You instantiate an abstract class by making a concrete class derived from it, and instantiating that. Remember, an instance of a derived concrete class is also an instance of its abstract base class. An instance of Giraffe is also an instance of Animal even if Animal is abstract.
Given that you can instantiate an abstract class, it needs to have a constructor like any other class, to ensure that its invariants are met.
Now, a static class is a class you actually cannot instantiate, and you'll notice that it is not legal to make an instance constructor in a static class.
It's a way to enforce a set of invariants of the abstract class. That is, no matter what the subclass does, you want to make sure some things are always true of the base class... example:
abstract class Foo
{
public DateTime TimeCreated {get; private set;}
protected Foo()
{
this.TimeCreated = DateTime.Now;
}
}
abstract class Bar : Foo
{
public Bar() : base() //Bar's constructor's must call Foo's parameterless constructor.
{ }
}
Don't think of a constructor as the dual of the new operator. The constructor's only purpose is to ensure that you have an object in a valid state before you start using it. It just happens to be that we usually call it through a new operator.
Key Points About Abstract Class
An abstract class cannot be instantiated.
An abstract class can have constructor and destructor.
An abstract class cannot be a sealed class because the sealed
modifier prevents a class from being inherited.
An abstract class contains abstract as well as non-abstract members.
An abstract class members can be private, protected and internal.
Abstract members cannot have a private access modifier.
Abstract members are implicitly virtual and must be implemented by a
non-abstract derived class.
Adding to the above answers and examples.
Yes, an abstract class can have a constructor, even though an abstract class cannot be instantiated. An abstract class constructor c# code example will be explained. But, the next question can also be arises, as if we cannot instantiate (construct an object using new) an abstract class, then what for a constructor is in an abstract class or why should we use a constructor in abstract class?
Note that when we create an object of a derived class then the constructor of the abstract base class is implicitly called, even though we cannot instantiate an abstract class. For example in the program, if we create an object of a derived class then the abstract base class constructor will also be called.
This is also one of the example
Examples
abstract class A
{
protected A() {Console.WriteLine("Abstract class constructor"); }
}
//Derived class
class B : A
{
public B() {Console.WriteLine("Derived class constructor"); }
}
class Program
{
static void Main(string[] args)
{
B obj = new B();
}
}
Output will be
Abstract class constructor
Derived class constructor
It's there to enforce some initialization logic required by all implementations of your abstract class, or any methods you have implemented on your abstract class (not all the methods on your abstract class have to be abstract, some can be implemented).
Any class which inherits from your abstract base class will be obliged to call the base constructor.
Normally constructors involve initializing the members of an object being created. In concept of inheritance, typically each class constructor in the inheritance hierarchy, is responsible for instantiating its own member variables. This makes sense because instantiation has to be done where the variables are defined.
Since an abstract class is not completely abstract (unlike interfaces), it is mix of both abstract and concrete members, and the members which are not abstract are needed to be initialized, which is done in abstract class's constructors, it is necessary to have constructors in the abstract class. Off course the abstract class's constructors can only be called from the constructors of derived class.
You are absolutely correct. We cannot instantiate an abstract class because abstract methods don't have any body i.e. implementation is not possible for abstract methods. But there may be some scenarios where you want to initialize some variables of base class.
You can do that by using base keyword as suggested by #Rodrick. In such cases, we need to use constructors in our abstract class.
You can instantiate it after you implemented all the methods. Then the constructor will be called.
I too want to make some shine on abstract surface
All answer has covered almost all the things. Still my 2 cents
abstract classes are normal classes with A few exceptions
You any client/Consumer of that class can't create object of that
class, It never means that It's constructor will never call. Its derived class can choose which constructor to call.(as depicted in some answer)
It may has abstract function.
Defining a constructor with public or internal storage class in an inheritable concrete class Thing effectively defines two methods:
A method (which I'll call InitializeThing) which acts upon this, has no return value, and can only be called from Thing's CreateThing and InitializeThing methods, and subclasses' InitializeXXX methods.
A method (which I'll call CreateThing) which returns an object of the constructor's designated type, and essentially behaves as:
Thing CreateThing(int whatever)
{
Thing result = AllocateObject<Thing>();
Thing.initializeThing(whatever);
}
Abstract classes effectively create methods of only the first form. Conceptually, there's no reason why the two "methods" described above should need to have the same access specifiers; in practice, however, there's no way to specify their accessibility differently. Note that in terms of actual implementation, at least in .NET, CreateThing isn't really implemented as a callable method, but instead represents a code sequence which gets inserted at a newThing = new Thing(23); statement.
an abstract class can have member variables that needs to be initialized,so they can be initialized in the abstract class constructor and this constructor is called when derived class object is initialized.
From https://msdn.microsoft.com/en-us/library/ms182126.aspx
Constructors on abstract types can be called only by derived types. Because public constructors create instances of a type, and you cannot create instances of an abstract type, an abstract type that has a public constructor is incorrectly designed.
Since only derived classes can use an abstract class constructor then an abstract class constructor, if needed, must be declared as protected.
However, that said VS compiler will not complain (with default rules) when declaring public constructors in abstract classes however it will not allow creating a new instance.
There are two following important features that prevent to inherit Abstract class
Abstract class must have an abstract method otherwise it is not a abstract class
Abstract class must be inherited by derived class,So if a class inherited by other class than what is use of to create object of that class

Is it possible to make a derived class inherit a non-0 argument constructor?

Building on my last question, is it possible to make a derived class inherit its base's constructor? For example, if I defined two classes like this:
class Base {
public Base(){}
}
public Derived() {
}
The base class's constructor will automatically be called when the derived class is instantiated. If I add another constructor to to the base class though,
class Base {
public Base(int x){}
}
Is it possible to construct the derived class using that constructor? I mean without having to add something like
public Derived() {
public Derived(int x) : base(x) {}
}
No, it isn't. You must explicitly add them; the only default is the parameterless constructor calling base(), which you get if you don't add any constructors. It might be nice in a few cases (especially when there are lots of constructors on the base), and I imagine there are some tools (maybe R# ? I haven't checked) that might help automate it - but nothing built in.
Sort of...
class Base {
protected Base() : this(default(int)) {}
public Base(int x){}
}
public Derived() {
}
Will force Derived to call the overloaded constructor with the default value of the argument. This may, or may not, be what you want to happen though. By marking the default constructor as protected, you prevent outside callers from instantiating with the default constructor but allow derived classes to do so.

Automatically making Base Constructors available in derived class?

I have a Base Class with two constructors, requiring a parameter:
public abstract class StoreBase
{
private readonly SomeObject_sobj;
protected StoreBase(SomeObject sobj)
{
_sobj = sobj;
}
protected StoreBase(OtherObject oobj)
{
_sobj = new SomeObject(oobj);
}
}
Then I have a derived class:
public class MyDerived: StoreBase
{
}
This causes a compilation error as base class doesn't contain parameterless constructor.
My understanding is that because MyDerived doesn't contain a constructor, the compiler adds a parameterless constructor (that's well known and nothing to do with derived classes). However, as it derives from another class, the base class constructor needs to run first, and there is no way to determine which constructor should run from the empty MyDerived constructor.
Basically I'm asking: can I avoid copy/pasting all constructors from Base into Derived class if I really don't need additional constructor logic? Can I say "Take all constructors from base" without adding them all?
(And yes, I know I could/should refactor this into a parameterless constructor and a protected virtual Initialize() method. but I still wonder if I can work with constructors and still avoid copy/paste)
No - you will need to implement the (appropriate) constructors in the derived class, as well.
The derived class only needs to use one of the base constructors - so the constructors required in it may be completely different than the base class. They will need to be implemented by hand, even if that's just:
public class MyDerived : StoreBase
{
public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}
}
Also:
(And yes, I know I could/should refactor this into a parameterless constructor and a protected virtual Initialize() method. but I still wonder if I can work with constructors and still avoid copy/paste)
Although I see this touted, I believe this is not always a good practice. In many cases, this is actually problematic, as you're relying on the subclass to properly call Initialize if they override your protected virtual method. For example, if the subclass did this, it could potentially be very bad:
public class MyDerived : StoreBase
{
// .. other stuff
protected override void Initialize()
{
// Leave out, intentionally or accidentally, the following:
// base.Initialize();
}
}
I actually avoid this in most situations, and initialize in the constructors (or in a private, non-virtual initialize method). Not doing this breaks any guarantees you have that your initialization will always occur the way you intend.
Constructors and constructor chaining provide the same functionality, with much better guarantees.
No, constructors are not inherited, and there is no shortcut for creating copies of the base constructors.
The closest is to implement constructors that call the base constructors. I guess you want to make them public anyway, so that you can actually create an instance of the class:
public MyDerived(SomeObject sobj) : base(sobj) {}
public MyDerived(OtherObject oobj) : base(oobj) {}
The compiler will only generate a default (parameterless) constructor if you haven't provided any constructor yourself. Once you define a constructor, the compiler won't generate one for you.
This can be important to keep in mind if you plan on serializing your class since serialization requires a default constructor. If your give your class a constructor other than a default one, then you'll also need to provide a default one to support serialization because, again, once you provide any constructor, the compiler won't provide one for you automatically.
Unfortunately the answer is no.
One thing you can do is call base from your MyDerived constructor:
class MyDerived: StoreBase
{
public MyDerived(OtherObject obj) : base (obj) {}
}
Can I say "Take all constructors from base" without adding them all?
No. :-(

Categories

Resources