views:

459

answers:

8

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

public abstract class MyClass {
    public abstract MyClass(int param);
}
+8  A: 

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
...and provide a body for it.
tvanfosson
It's also a good practice to declare constructors in abstract classes as **protected**. It enforces the fact that the class cannot be directly instantiated.
Yann Trevin
@tvanfosson: Thanks for pointing that out. I missed that when I read the question.
Zach Johnson
A: 

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

Michael Bray
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
I see your point. However, the intention of the question was more related to inheritance.
Michael Bray
+14  A: 

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
{
     public Bar() : base("bar")
     {
        ...
     }
}
tvanfosson
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
I've updated and clarified.
tvanfosson
+1  A: 

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: http://stackoverflow.com/questions/1788312/why-constructor-not-returns-value

Daniel Earwicker
+3  A: 

Because abstract constructors are not supported.

But a abstract class can have a constructor.

Davy Landman
+3  A: 

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
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
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
Small clarification - they are not *obliged* to call it, but they *may* call it.
slugster
In my example they oblige to call MyClass(int param) but they may pass invalid data.
Sergey Teplyakov
+4  A: 

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
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
+3  A: 

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
+1 for the reflection use case.
fre0n