I have a set of classes where my base has a constructor that takes a configuration object and handles transferring the values to its properties.
abstract class A { public A(ObjType MyObj){} }
abstract class B : A {}
class C : A {}
class D : B {}
class E : B {}
Is it possible to implicitly call a non-default base constructor from child classes or would I need to explicitly implement the signature up the chain to do it via constructors?
abstract class A { public A(ObjType MyObj){} }
abstract class B : A { public A(ObjType MyObj) : base(MyObj){} }
class C : A { public A(ObjType MyObj) : base(MyObj){} }
class D : B { public A(ObjType MyObj) : base(MyObj){} }
class E : B { public A(ObjType MyObj) : base(MyObj){} }
If that is the case, is it better to just implement a method in the base then have my factory immediately call the method after creating the object?
Implicitly? No, constructors are not inherited. Your class may explicitly call it's parent's constructor. But if you want your class to have the same constructor signatures as the parent class's, you must implement them.
For example:
public class A
{
public A(int someNumber)
{
}
}
// This will not compile becase A doesn't have a default constructor and B
// doesn't inherit A's constructors.
public class B : A
{
}
To make this work you'd have to explicitly declare the constructors you want B to have, and have them call A's constructors explicitly (unless A has a default constructor of course).
public class B : A
{
public B(int someNumber) : base(someNumber)
{
}
}
No it's not possible to call a non-default base constructor implicitly, you have to make it explicit.
You need to explicitly implement it up the chain. Also, importantly, in your original code, you will not be able to call a new B(), since A does not have a default constructor, and B does not call A's constructor that has an arg.
Related
I have an abstract base class from which I derive two classes. The abstract class has a protected field which is initialized by constructors in the derived classes. Each of the derived classes has two constructors, the first constructor of each class initializes the field and the second constructor modifies the initialization of the first by calling the first constructor. The second constructor of both derived classes are exactly the same but the first constructor is different between the two derived classes. Is there some way to put the second constructor in the base class?
Here is an example to illustrate what I'm trying to say:
public abstract class A {
protected int[] field1;
public void someMethod() {
//somethingsomething
}
}
public class B : A {
public B() {
//body X
//this initializes field1 in some way
}
public B(bool p) : this() {
//body Y
//this initializes field1 in some way + modification
}
}
public class C : A {
public C() {
//body Z
//this initializes field1 in another way
}
public C(bool p) : this() {
//body Y
//this initializes field1 in another way + modification
}
}
What I would like to do, is to find some way so as to not have to repeat body Y twice. I was thinking of putting body Y of B(bool p) and C(bool p) in a constructor in class A as A(bool p), then have B(bool p) and C(bool p) call the base class constructor with : base(bool p) followed by an empty body, but then realized the base class constructor would have to call the derived class constructor.
This sounds stupid to me too. Although I am not sure, it's because I have this feeling that calling something from a derived class from a base class is something that can only be done at run time and there really is no way to check this at compile time. I'm just trying to find a way to follow the DRY principle.
Thanks.
Short answer: no. That would be breaking the object-oriented paradigm, so you wouldn't want to be able to do that anyway. Think about it this way: an abstract base class can be extended by an arbitrary number of classes, but if it was tightly coupled to one of the child classes, how would that impact the other ones?
public class BaseClass {
// Call child class constructor
public BaseClass() : A() { }
}
public class A : BaseClass {
public A() { ... }
}
// How should BaseClass handle this? There is no constructor named "A."
public class B : BaseClass {
public B() { ... }
}
If you want the base class and derived class to share some functionality, you should make it a protected method in the base class. That way, you can call that method from the constructor.
You could also make a constructor on the base class that provides the common functionality and call it from the child class with : base(...).
The only way a base class can trigger a derived behavior is through polymorphism (having a virtual method in B, and overriding it).
But there's some other way that might be much more inuitive in your case. For example:
public class C : A {
public C() {
//body Z
//this initializes field1 in another way
}
public C(bool p) : base(p) {
//this initializes field1 in another way + modification
}
}
Please note that in your example, B's default constructor calls A's default constructor, as well as C's default one calls B's default one.
Lastly, you can also consider having a second constructor in A that receives field1 initial value as a parameter, but it depends if your instructions are order-dependent.
If you precise what your constructors do exactly, I might have a more decisive answer for you.
Sincerely,
I am writing an abstract base class. I want all the classes that inherit from it to inherit a constructor that basically does the same things for all the classes. Is this possible?
Doing your constructor protected will do the stuff
public abstract class A
{
protected A(string v) { V = v; }
public string V { get; protected set; }
}
public class AA : A
{
public AA(string v) : base (v) {}
}
If the abstract base class has a default constructor (i.e. a constructor with no parameters), it will automatically be called by the derived classes constructors, unless they explicitly call another constructor of the base class.
abstract class B
{
protected B()
{
...
}
protected B(object foo)
{
...
}
}
class D : B
{
public D()
: base() // not actually necessary, since it's called implicitly
{
}
public D(object foo)
: base(foo)
{
}
}
In your derived classes constructor, you will need to call your base constructor like so:
base(param1,param2,...)
If you do not call the base constructor explicitly, the default constructor in the base class will be called, if one exists. If not, you will get a compile error.
I have a class like below
public abstract class ABC
{
int _a;
public ABC(int a)
{
_a = a;
}
public abstract void computeA();
};
Is it mandatory for the derived class to supply the parameters for the base/abstract class constructor? Is there any way to initialize the derived class without supplying the parameters?
Thanks in advance.
Yes, you have to supply an argument to the base class constructor.
Of course, the derived class may have a parameterless constructor - it can call the base class constructor any way it wants. For example:
public class Foo : ABC
{
// Always pass 123 to the base class constructor
public Foo() : base(123)
{
}
}
So you don't necessarily need to pass any information to the derived class constructor, but the derived class constructor must pass information to the base class constructor, if that only exposes a parameterized constructor.
(Note that in real code Foo would also have to override computeA(), but that's irrelevant to the constructor part of the question, so I left it out of the sample.)
You can create a default constructor in a derived class that does not need parameters and the derived class will supply default values, but you cannot remove the requirement entirely. It is a manadatory condition of the base class to have some sort of value.
public MyDerivedClass : ABC
{
public MyDerivedClass()
: base(123) // hard wired default value for the base class
{
// Other things the constructor needs to do.
}
public override void computeA()
{
// Concrete definition for this method.
}
}
Add a default constructor to the base class and call the other constructor providing an initial values for its parameters:
public abstract class ABC
{
int _a;
public ABC(int a)
{
_a = a;
}
public ABC() : this(0) {}
}
It doesn't have much to do with the fact that the base class is abstract.
Because you've declared a public constructor that has 1 parameter, the compiler removes the basic empty constructor.
So, if you want to create an instance of that class, you have to pass a parameter.
When you derive from such a class, a parameter must be passed to the base class for it o construct.
I have tried to understand but still not sure. If there is a constructor in the base class, the derived classes will always call it? I know they can override it (not correct term here, I know - I mean add code to their constructors) but I assume if the constructor is defined in the base class, the derived ones will always call it. Is that true?
Yes, if there is a parameterless constructor it will always be called. If there is more than one constructor, you can choose which one to call with the base keyword:
class Parent {
public Parent() {}
public Parent(int x) {}
}
class Child : Parent {
public Child(int x) : base(x) {
}
}
If there is no parameterless constructor, you will be forced to do this:
class Parent {
public Parent(int x) {}
}
class Child : Parent {
// This will not compile without "base(x)"
public Child(int x) : base(x) {
}
}
If there is only a parameterless constructor in the base class, the child class constructor will always call it first. On the other hand if you have other constructors defined in the base class, then the child class will have an option which base constructor to call.
How and when to call the base class constructor in C#
You can call the base class constructor like this:
// Subclass constructor
public Subclass()
: base()
{
// do Subclass constructor stuff here...
}
You would call the base class if there is something that all child classes need to have setup. objects that need to be initialized, etc...
Hope this helps.
It's usually a good practice to call the base class constructor from your subclass constructor to ensure that the base class initializes itself before your subclass. You use the base keyword to call the base class constructor. Note that you can also call another constructor in your class using the this keyword.
Here's an example on how to do it:
public class BaseClass
{
private string something;
public BaseClass() : this("default value") // Call the BaseClass(string) ctor
{
}
public BaseClass(string something)
{
this.something = something;
}
// other ctors if needed
}
public class SubClass : BaseClass
{
public SubClass(string something) : base(something) // Call the base ctor with the arg
{
}
// other ctors if needed
}