57

Possible Duplicate:
Why can’t I create an abstract constructor on an abstract C# class?

Why I can't declare abstract an constructor of my class like this:

public abstract class MyClass {
    public abstract MyClass(int param);
}
Community
  • 1
  • 1
AndreyAkinshin
  • 18,603
  • 29
  • 96
  • 155
  • 3
    It seems like the constructor is an implementation detail, and therefore forcing subclasses to be constructed in a certain way would be a bad thing. If you want an encapsulated construction, use the static factory pattern. – Michael Meadows Feb 19 '10 at 19:52
  • Looks like he wants something that isn't possible with the current genericss, structural subtyping/parameter-taking constructor. – Dykam Feb 19 '10 at 20:09
  • What is it that you're trying to accomplish? Perhaps there is another way of looking at it. – fre0n Feb 19 '10 at 20:21
  • 13
    Suppose you had such a constructor. *What would you do with it?* You cannot *call* it, because its abstract. You cannot *override it* because constructors are not overridable. You can't do *anything* with it. Therefore, there's no reason to make it legal. – Eric Lippert Feb 19 '10 at 20:29
  • 5
    Obviously, he doesn't know that you can't override constructors or else why would he want to create an abstract one? – Cruiser Nov 22 '11 at 21:14
  • Eric, what I wanted to do with this is make sure that derived classes implement a constructor that can create an object from, say a string, or a file. I can define an interface to define all other class behavior, but when it comes to constructing an object, why can't I do the same? – Igor Yagolnitser Jul 15 '16 at 22:29

8 Answers8

89

Constructors are only applicable to the class in which they are defined, that is, they are not inherited. Base class constructors are used (you have to call one of them, even if only calling the default one automatically) but not overridden by deriving classes. You can define a constructor on an abstract base class -- it can't be used directly, but can be invoked by deriving classes. What you can't do is force a derived class to implement a specific constructor signature.

It is perfectly reasonable to have a constructor defined, typically as protected, in order to define some common set up code for all derived classes. This is especially true, perhaps, when the abstract class provides some other default behavior which relies on this set up. For example:

public abstract class Foo
{
     public string Name { get; private set; }

     protected Foo( string name )
     {
         this.Name = name;
     }
}

public class Bar : Foo
{
     public Bar() : base("bar")
     {
        ...
     }
}
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 7
    You're not wrong, but I'd clarify one thing: Constructors aren't inherited, but they *are* called by children. Your only choice is *which* constructor to chain to from yours. – Steven Sudit Feb 19 '10 at 19:51
  • 1
    @tvanfosson: _you probably meant `Bar` to inherit `Foo`_ – comecme Jun 29 '12 at 22:10
  • @comecme - funny, I missed that...and such a long time ago, too. thanks for pointing it out. – tvanfosson Jun 30 '12 at 01:45
  • +1 "...What you can't do is force a derived class to implement a specific constructor signature." - Exactly what I as looking for, thanks – turkinator Mar 15 '16 at 15:22
12

You can't declare it abstract, but you can have a constructor on your abstract class; just remove the word abstract and provide a body for it.

Zach Johnson
  • 23,678
  • 6
  • 69
  • 86
9

Constructors are closer to static methods rather than "regular" methods. Like static methods, they can be overloaded, but not overriden. That is, they are not inherited but can be redefined.

public BaseClass
{
   public BaseClass( String s ) { ... }
   public static void doIt ( String s ) { ... }
}

public SubClass extends BaseClass
{
   public SubClass( String s )  { ... }
   public static void doIt ( String s ) { ... }
}

public SubClass2 extends BaseClass
{
}

new SubClass( "hello" );
SubClass.doIt( "hello" ); 

new SubClass2( "hello" ); // NOK
SubClass2.doIt( "hello" ); // NOK

Constructors and static methods are never dispatched dynamically (virtually) -- You always know the concrete type you instantiate or the concrete class of the static method. That's why it makes no sense to have abstract constructor and abstract static method. That's why you can also not specify constructor and static method in interfaces.

You can even think of constructor as static factory method (and see the corresponding pattern):

  MyClass obj = new MyClass(); // the way it is
  MyClass obj = MyClass.new(); // think of it like this

The only case I see where it would make sense to define abstract constructor or abstract static method would be if reflection is used. In this case, you could ensure that all subclass would redefine the corresponding static method or constructor. But reflection is another topic...

Note: in languages such as Smalltalk where classes are regular objects, you can override static method and have abstract constructor. But it doesn't apply to Java because classes are not "regular" objects even if you can get them with reflection.

ewernli
  • 38,045
  • 5
  • 92
  • 123
6

Abstract implies virtual. A non-default constructor can never be called polymorphically, so virtual and abstract are not allowed on constructors.

IF in a future version of C#, generics are enhanced to allow calling non-default constructors through a generic type parameter, then polymorphic calls to constructors would be possible and virtual and abstract constructors might be added as well.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 2
    Calling a non-default constructor in a generic method is still not a polymorphic call, because the type is known in advance. A constructor can never be called polymorphically, period. – Anton Tykhyy Feb 19 '10 at 19:53
  • @AntonTykhyy: Calls in generic context *are* polymorphic. .NET generics work based on type erasure and virtual dispatch. They are not specialized per-type the way that C++ templates are. – Ben Voigt Dec 29 '16 at 15:35
  • That's if you ignore value types. Generics closed over value types _are_ specialized. Just imagine how horrible `List` etc. would be otherwise. But I see what you mean. I suppose one could add a slot in `RuntimeTypeHandle` for each constructor used in a generic constraint. But what if later somebody loads an assembly that has a new generic constructor constraint? All existing `RuntimeTypeHandle`s would have to be updated. Not saying it can't be done, just a lot of hassle. – Anton Tykhyy Mar 14 '17 at 12:12
  • @AntonTykhyy: They aren't specialized in the C++ template specialization sense, but yes the codegen instantiates generics separately for each value type. However, value types can't inherit from a base class, only implement interfaces. So you'd need a generic constrained by an interface, where the actual generic type is a value class, in order to get the specific codegen. – Ben Voigt Mar 14 '17 at 14:10
  • Not just that. What if some methods in the generic declare locals of type `T : struct` and/or manipulate them? I suppose you could just stick `sizeof (T)` somewhere in the method table and use the equivalents of `alloca` and `memcpy` with the size parameter (though `alloca` is inconvenient in x64), and maybe that's what the jitter does for large structs, but the performance would be horrible for primitives. Again, consider `List`. Maybe `List` shares some codegen with `List` and `List`, though (except `List.Sort()` etc.) – Anton Tykhyy Mar 16 '17 at 10:49
  • @AntonTykhyy: Yes you get different machine code for each (combination of) value type on a generic. But no specialization, and because there's not even overload resolution, it's weaker even than template instantiation. That is, if you have `f(object)`, `f(int)`, `f(float)`, and `g(T t) { f(t); }`, then `g(int)` will call `f(object)` in C# and `f(int)` in C++. I 100% stand by my previous statement that ".NET generics are not specialized per-type the way that C++ templates are". – Ben Voigt Mar 16 '17 at 13:53
  • Of course not, these are entirely different mechanisms. – Anton Tykhyy Mar 17 '17 at 22:05
4

What wrong with this:

public abstract class MyClass {
    protected MyClass(int param)
    {
    }
}

In this case you oblige all derived classes to call base class constructor.

Sergey Teplyakov
  • 11,477
  • 34
  • 49
  • 1
    It does force the class to declare a constructor, but not necessarily one with that takes an integer parameter. You could easily declare it as `public class NewClass : MyClass { public NewClass() : base(0) { } }` – tvanfosson Feb 19 '10 at 19:47
  • You can use argument validation in MyClass constructor and throw exception due to invalid argument. But you can't force derived classes to pass valid data to MyClass constructor and do not add additional constructors in derived classes. – Sergey Teplyakov Feb 19 '10 at 19:50
  • 1
    Small clarification - they are not *obliged* to call it, but they *may* call it. – slugster Feb 19 '10 at 19:54
  • 5
    In my example they oblige to call MyClass(int param) but they may pass invalid data. – Sergey Teplyakov Feb 19 '10 at 19:58
  • 2
    Which one of you is telling the truth here? slugster or Sergey? Is or isn't the derived class obligated to pass an int? – comecme Jun 29 '12 at 22:16
3

Because abstract constructors are not supported.

But a abstract class can have a constructor.

Davy Landman
  • 15,109
  • 6
  • 49
  • 73
1

A constructor is not an ordinary method. It has a special purpose, and so is restricted to language features that make sense for that purpose. See also: Why do constructors not return values?

Community
  • 1
  • 1
Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
0

By definition, the class can't be instantiated directly, so in a sense, it already is abstract.

Michael Bray
  • 14,998
  • 7
  • 42
  • 68
  • Abstract methods have no body until it is provided by a derived class. This is definitely not true of constructors of abstract classes. – Ben Voigt Feb 19 '10 at 19:53
  • I see your point. However, the intention of the question was more related to inheritance. – Michael Bray Feb 19 '10 at 19:55