263

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?

Canovas
  • 99
  • 11
Mulder
  • 2,817
  • 3
  • 17
  • 7

15 Answers15

348

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){}

}
Pere
  • 1,068
  • 12
  • 20
Craig Suchanec
  • 10,474
  • 3
  • 31
  • 39
  • 3
    But abstract class is defined as a class which we cant instantiate it.. if I use it to initialize an readonly variable on base class which is abstract is it okay? – Mulder Apr 08 '11 at 23:37
  • 7
    Yes, if I understand you correctly. You can't instantiate the abstract class itself but the derived class still has all the pieces of the base class. Its not only valid to do it, its one of the primary reasons why you would do it. – Craig Suchanec Apr 08 '11 at 23:39
  • ok , now if I have a first level abstract class which inherits from other abstract class(second level) and third class ( not abstract class) inherit from the second layer abstract class, how can I initialize a readonly variable which is declared on the first layer abstract class from within the c'tor of the third normal class I need to go up two levels up to the c'tor – Mulder Apr 08 '11 at 23:57
  • 1
    The only way I really can think to do that is something like the following: public abstract class A { protected readonly string data; protected A(string myData) { data = myData; } } public abstract class B :A { protected B(string myData): base(myData){ } } public class C : B { C(string myData): base(myData){ } } – Craig Suchanec Apr 09 '11 at 00:11
  • So when you call new B() does it call the constructor on the parent class? – ndtreviv Oct 08 '20 at 14:00
  • The example @CraigSuchanec gave is a little hard to read. Let me see if I can format it better and call out the relevant pieces: `public abstract class A { protected readonly string data; protected A(string myData) { data = myData; } } public abstract class B : A { protected B(string myData) : base(myData) { } // base here is the A constructor } public class C : B { public C(string myData):base(myData) { } // base here is the B constructor } }` – Andy Nov 10 '20 at 17:23
  • That isn't MUCH easier to read since stack overflow removed my line breaks, but hopefully the comments make it slightly easier to see. Class C's constructor calls class B's constructor prior to the C constructor body being executed. Class B's constructor calls A's constructor prior to the B constructor body being executed. – Andy Nov 10 '20 at 17:28
280

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.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 4
    From a terminology perspective, if `Foo` is an inheritable concrete type, and `DerivedFoo:Foo`, what term would you use to describe a heap object instance which will report its type as `Foo`, as distinct from `DerivedFoo`? My own inclination would be to use the phrase "an instance of T" to refer to something whose *exact* type is T. Otherwise I'd be inclined to say something like "a T or some derivative", "some derivative of T", "some implementation of T", or "something satisfying T" depending upon whether T is a concrete class, abstract class, interface, or constraint. – supercat Sep 03 '13 at 17:39
  • 41
    Using that logic you can get instances of interfaces :-) – G. Stoynev Jan 09 '14 at 20:25
  • 11
    @Eric http://msdn.microsoft.com/en-us/library/sf985hc5.aspx Says abstract class cannot be instantiated – Nipuna Jul 09 '14 at 06:21
  • 1
    Good answer though your comment about static classes not being instantiated might be a bit misleading. Unless I misunderstand, (unique) static types are, in fact, instantiated once and only once per AppDomain. The client application implicitly causes this instantiation the first time it references a member of the static type. – M.Babcock Nov 26 '14 at 01:34
  • 4
    @M.Babcock: The static *initializers* are run, but no *instance* of the type is created. – Eric Lippert Nov 26 '14 at 14:43
  • So you've got [Polymorphism](https://msdn.microsoft.com/en-us/library/ms173152.aspx) huh? :) – yazanpro Mar 21 '15 at 03:44
  • 4
    @supercat Unfortunately that's a semantic misunderstanding that leads to misuse of polymorphism. A Giraffe "IS A" Animal. An instance of Giraffe is an instance of Animal also, and must be usable in every place where an instance of Animal is required. Eric is absolutely correct here. Insisting that the instance of Giraffe is not exactly an instance of Animal can lead to dangerous anti-patterns like allowing Rectangle be a subclass of Square even though it is does not maintain the same invariants and is not strictly substitutable. – GrandOpener Sep 22 '15 at 14:48
  • @GrandOpener: What is meant by "a giraffe"? In most OOP languages, a variable of type "Animal" holds either null or else a *reference* to an object instance, and there is no problem with the concept of a reference-of-type-Animal identifying an instance-of-type-Giraffe. In a language like C++ where variables can hold actual instances, it will often not be possible to store a `Giraffe` into a variable of type `Animal` unless `Giraffe` and `Animal` have the same fields [one of which could be a pointer to supplemental data]. – supercat Sep 22 '15 at 14:56
  • 1
    @supercat My answer was about C#, but I don't see how C++ changes things much. Even if you are not using pointers and slice off the extra data from a Giraffe instance, you are still left with a perfectly valid Animal instance that can do anything an Animal needs to do, you just no longer actually have a Giraffe. That's usually not what is expected/intended, but it is consistent with the idea that what you had was a valid Animal instance from the beginning, even though you created it with a Giraffe constructor. – GrandOpener Sep 22 '15 at 20:43
  • @GrandOpener: If an instance of Giraffe really were an instance of type Animal, then it would be possible to store an instance of Giraffe into a variable of type Animal *and still have it be an instance of Giraffe*. The fact that a Giraffe is convertible to Animal doesn't show that a Giraffe "is" an Animal, but quite the opposite--if a Giraffe really were an Animal, no conversion would be required. – supercat Sep 22 '15 at 21:44
  • 1
    @supercat If an instance of Giraffe were not an instance of Animal, then it wouldn't be possible to store it in the variable of type Animal in the first place. All Giraffes are Animals, but not all Animals are Giraffes. To be more specific, `auto g = Giraffe()`. The object stored in g is an instance of Giraffe, and it is also an instance of Animal. `void f(Animal){...} f(g)`, this is valid because g is an instance of Animal. (No "conversion" is applied, only slicing.) `Animal a = g`. Now, variable a holds an instance of Animal. The a is an Animal but not a Giraffe. – GrandOpener Sep 23 '15 at 12:23
  • @GrandOpener: Are you saying that the legality of `float f=16777217;` implies that `16777217` is a `float`? Suppose `Giraffe` has a field `neck_length` not present in animal, and its virtual `sleep()` method increments `neck_length`. I would posit that if something is a legitimate instance of `Giraffe`, calling `sleep()` on it should increment `neck_length`. What will be the effect of storing a `Giraffe` in a variable of type `Animal` and calling `sleep()` on it? – supercat Sep 23 '15 at 16:34
  • 1
    @supercat _"Are you saying that the legality of float f=16777217; implies that 16777217 is a float?"_ No, I think you've got my reasoning backwards. If 16777217 were an instance of a theoretical subclass of float (pretending for a moment that's possible) then it would be assignable to f because it is also a float. In actuality 16777217 is assignable to f because an implicit conversion exists from int to float. As to the other example, if you slice a Giraffe, then it is still an Animal, but it is no longer a Giraffe. It will not behave like a Giraffe, which is why slicing is usually a bug. – GrandOpener Sep 23 '15 at 17:56
  • @GrandOpener: You recognize that 16777217 is implicitly convertible to float, but isn't a float; I would suggest that an instance of Giraffe is likewise implicitly convertible to an instance of Animal, but isn't an instance of Animal. If an instance of Giraffe really were an instance of Animal, it should be possible for a variable of type Animal to hold an instance of type Giraffe, which you acknowledge is not possible. Note that a pointer to a Giraffe *is a* pointer to an Animal, since even when stored it in a variable of type "pointer to Animal", it will still point to a Giraffe. – supercat Sep 23 '15 at 18:32
  • 1
    @supercat Well, I understand your suggestion, but I (along with what I have read in MSDN, Wikipedia, and Design Pattern textbooks) disagree with the definition that you have chosen. I thought you didn't understand what I was saying, but it seems that perhaps you simply disagree. If so, we should take any further discussion to chat, rather than continuing to clog up the comments here. – GrandOpener Sep 23 '15 at 18:46
  • 1
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/90470/discussion-between-supercat-and-grandopener). – supercat Sep 23 '15 at 19:38
  • seems like you can implicitly create an instance of an abstract class by creating an instance of one of its derived classes. – conterio Jul 26 '16 at 15:58
  • The compiler creates an instance of all static classes at compile time. But you may not! – conterio Jul 26 '16 at 16:09
  • @Nipuna Reread quickly. You can't **directly instantiate** an abstract class like this: `Animal animal = new Animal();` but you **certainly can** do this: `Animal animal = new Giraffe();` I had to double-take myself. Reread this: "*You instantiate an abstract class by **making a concrete class derived from it**, and instantiating that... 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.*" Does seem unintuitive: I can't have methods [with code], but I can have a constructor? But this use case shows why. – ruffin Apr 05 '17 at 17:51
  • 1
    @ruffin: An abstract class can have methods with code; a constructor is such a method. – Eric Lippert Apr 05 '17 at 19:47
  • @EricLippert Ah. Didn't realize constructors were also methods. I meant a method marked abstract doesn't compile (*[Method] cannot declare a body because it is marked abstract*) though a "constructor marked abstract" does. But that's my mistake -- As you can't label a constructor `abstract` (*The modifier 'abstract' is not valid for this item.*), I mentally kludged that the abstract nature of the class extended to its constructors. That's wrong, & though it still feels incongruous (Why not use a base class if you want code?), I appreciate your explaining why I'm wrong in your answer & comment. – ruffin Apr 06 '17 at 16:54
  • 1
    @ruffin: It sounds like from your comments that you believe that an abstract class may not contain concrete methods. An abstract class may contain concrete methods. Just don't mark them "abstract" if they're not abstract. An abstract method is by definition a method without an implementation; that's what makes it *abstract*. – Eric Lippert Apr 06 '17 at 17:05
  • I had `abstract method:method::abstract class:class`, but mistakenly also had `abstract method:method::abstract class' constructor:class' constructor` (in part b/c you couldn't have an abstract constructor), and I think that screwed up all sorts of abstract class conceptions you've set straight. I now *think* the only pro for using abstract classes with code *in the constructor* over base classes is that the former can't be *directly* instantiated -- and not catching that distinction (w/out which I'd just make a base class) is why I searched up the OP's question. Thanks! – ruffin Apr 06 '17 at 17:55
  • 4
    Don't tell "Of course you can instantiate an abstract class" in the interview. – Zafar Jan 04 '18 at 05:09
  • I feel like this answer is unnecessarily pedantic. Of course you can _indirectly_ instantiate an abstract class, but that's obviously not what the OP meant. – Clonkex Jul 26 '22 at 01:19
  • 1
    @Clonkex: It was by no means obvious to me what the original poster meant; what the OP *said* was "we cannot instantiate an abstract class" which is incorrect. Plainly the original poster does not understand *something* because (1) they're asking a question; if they understood, they wouldn't ask, and (2) they're making false statements. By correcting the false statement maybe we can answer the question. But if you feel this answer to an 11-year old question is bad in some way, why not write an answer you like better, and show us what a good answer looks like? – Eric Lippert Jul 26 '22 at 17:30
25

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.

forsvarir
  • 10,749
  • 6
  • 46
  • 77
Rodrick Chapman
  • 5,437
  • 2
  • 31
  • 32
  • 10
    You don't need to call `base()` on derived class' constructor. It will get called automatically, because that's the parameterless constructor. This means that your constructor is equivalent to `public Bar() {}`. – Robert Koritnik Nov 14 '11 at 17:26
  • 1
    @RobertKoritnik - that's odd since I can't recall or even imagine a time when I did not know that but there it is. – Rodrick Chapman Mar 20 '13 at 23:29
  • 3
    side note/comment; I like the fact that you used the words; odd and even in the same sentence. – Chef_Code Oct 06 '16 at 22:44
7

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
akhil
  • 1,649
  • 3
  • 19
  • 31
6

Key Points About Abstract Class

  1. An abstract class cannot be instantiated.
  2. An abstract class can have constructor and destructor.
  3. An abstract class cannot be a sealed class because the sealed modifier prevents a class from being inherited.
  4. An abstract class contains abstract as well as non-abstract members.
  5. An abstract class members can be private, protected and internal.
  6. Abstract members cannot have a private access modifier.
  7. Abstract members are implicitly virtual and must be implemented by a non-abstract derived class.
Sakib
  • 171
  • 1
  • 9
5

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.

2

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.

Rohan Rao
  • 2,505
  • 3
  • 19
  • 39
1

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.

zafar
  • 1,965
  • 1
  • 15
  • 14
1

Using abstract classes is a way of standardizing your code. It can also be considered as a way of preparing a template or blueprint for other classes. Think about different types of cars that are available now days :- SUV, Sedan, Coupe, Hatchback etc. All have the same basic blueprint, for instance they all have steering, brake, clutch etc. But still there are many features and functionalities that are different in all the cars. So we can think of it as that an abstract class of car has been declared that includes the standardized methods/features that need to be implemented by all the cars but additionally the different types of cars can add their own features/functionalities as well. Now coming to your question and relating it to the example given above. See if we have to make a car obviously it would be one of a kind mentioned above (SUV,Sedan.....) i.e. for creating an instance of abstract class we need to inherit it. That is why it is termed as "must inherit class". If the constructor is also being included in the abstract class then it means that all the derived classes would also need to use a constructor as well. And if we are running a code of this kind :-

public abstract class AbstractClass
{
    public AbstractClass()
    {
        Console.WriteLine("Abstract class constructor");
    }
}
public class derived : AbstractClass 
{ 
    public derived()
    {
        Console.WriteLine("Derived class constructor");
    }
}
class Program
{
    public static void Main(string[] args)
    {
        derived d= new derived();
        Console.ReadLine();
    }
}

Then the output would be :-

    Abstract class constructor
    Derived class constructor

which clearly shows that constructor can also be used in abstract classes.

0

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

  1. 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)
  2. It may has abstract function.
Sumit Kapadia
  • 387
  • 2
  • 9
0

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.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
supercat
  • 77,689
  • 9
  • 166
  • 211
0

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.

waqar ahmed
  • 335
  • 2
  • 6
0

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.

Ahmad
  • 1,462
  • 15
  • 23
0

You can instantiate it after you implemented all the methods. Then the constructor will be called.

Servy
  • 202,030
  • 26
  • 332
  • 449
duedl0r
  • 9,289
  • 3
  • 30
  • 45
-2

There are two following important features that prevent to inherit Abstract class

  1. Abstract class must have an abstract method otherwise it is not a abstract class

  2. 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

maazza
  • 7,016
  • 15
  • 63
  • 96
pawan
  • 1
  • 1