49

It is not possible to create an object by directly calling the constructor of an abstract class. The constructor of an abstract class can be called only from a derived class. It therefore seems to me that constructors of an abstract class must be either protected or package-private (the latter for the unusual cases of restricting use of a constructor to derived classes within the package). Yet Java allows the constructor of an abstract class to be public.

Are there any circumstances in which it is useful to declare the constructor of an abstract class to be public, rather than protected or package-private?

This is not quite a duplicate of the question "Abstract class constructor access modifier": clearly you can declare a constructor to be public; I want to know whether there is ever any good reason to do so. It seems to me that there is not. I see that C# has a similar peculiarity.

Community
  • 1
  • 1
Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • Constructor has nothing to do with "Creation" of object. It is just a method that is called while "creating" an object. Thus, Abstract class can have public constructors that would be called while creating instance of Abstract class (via Subclass) and in that constructor-method, you would write code to initialize the member variables. http://stackoverflow.com/questions/260666/can-an-abstract-class-have-a-constructor?lq=1 – Sandeep Jindal Jun 28 '13 at 18:05
  • 1
    Constructors can also be `private`, which can be used in constructor chaining. – Brian McCutchon Mar 12 '14 at 00:32
  • Possible duplicate of [Can an abstract class have a constructor?](https://stackoverflow.com/questions/260666/can-an-abstract-class-have-a-constructor) – 8protons Oct 08 '19 at 17:50

4 Answers4

28

The answer is the same for java:

THere's no reason for a public constructor for an abstract class. I'd assume that the reason that the compiler doesn't complain is as simple that they just didn't spend time covering that since it really doesn't matter if it's public or protected. (source)

You can't call a constructor of an abstract class from anything other than a direct subclass.

So adding a special rule for access modifiers of constructors of abstract classes wouldn't add something useful to the language.


One thing that looks like an exception from this rule - if the abstract class only defines a default constructor, then the subclass does not have to implement a constructor: this is legal:

public abstract class A {
  public A() {}
}

public class B extends A {}

So we can create a B by calling new B() - but note, that we still create a B and not an A. And, again, it doesn't matter if the constructor in A is public or protected. It just shouldn't be private, but the compiler will notice and complain...

Actually we invoke an "invisible" public default constructor on B which does a simple super() call...

Community
  • 1
  • 1
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
0

The visibility also infuences what is shown in the javadoc (if it's selected to exclude certain visibility levels). As it doesn't matter otherwise, that could be a usage for a public constructor of an abstract class.

If you provide no constructor, then the default constructor is public if the class is public. Easiest option would be to allow that, rather than forcing protected constructors.

In that sense the reverse question may make it clear: why didn't they force protected constructors in abstract classes? Because public constructors won't change anything, so it would just take time and add complexity.

wjs
  • 61
  • 1
  • 5
-7

Call me a heretic, but ... I see at least one use for a constructor in an abstract class.

That is: to specify what the constructor parameters look like.

Specify an abstract constructor (thus making the class abstract). Derived classes have to implement this constructor with its specific signature to lose abstract status.

I see no other way to specify mandatory constructor signatures (help me out if you do).

foo
  • 1,968
  • 1
  • 23
  • 35
  • 3
    Making the constructor `protected` still allows you to "specify what the constructor parameters look like". – Raedwald Mar 29 '14 at 10:35
  • true, but doing so requires the derived class to call super() or risk missing init steps that might occur. Abstract clarifies this is the signature only, no implementation. - It would be best if interfaces allowed to specify the constructor signature. But since they don't, I consider abstract classes the next best thing. – foo Mar 31 '14 at 17:55
  • 3
    You can not avoid calling `super`. It is called implicitly if you do not explicitly call it. – Raedwald Mar 31 '14 at 18:18
  • the point is not to avoid calling `super`, the point is to specify the constructor signature. – foo Mar 15 '16 at 02:44
  • Just to clarify, this idea doesn't even work. `abstract` is not a legal modifier for a constructor, you make a class abstract by modifying the class declaration. There's no way in Java to mandate constructor signatures for subclasses, they are never inherited. – Sean Van Gorder Jun 27 '16 at 14:51
  • I am fully aware that the Java language specification does not allow for this; I was making a point why it would be useful if it did. – foo Aug 09 '16 at 10:09
-10

You can have a public constructor if you do not define in a constructor in the sub-class. example

abstract class Animal {
   String name;
   public void Animal(String name) {
         this.name = name;
   }
}


class Cat extends Animal{
    public String sayMayName() {
       return this.name;
    }
}

myCat = new Cat("tester");

name = myCat.sayMyName();

if no constructor is defined the parent class constructor will be called, if it is not public it will not work. This I think is more elegantly done with a factory pattern, but I used it in practice in PHP and it works fine.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Catalin Marin
  • 1,252
  • 1
  • 11
  • 18
  • 5
    This does not work in Java. Also, you're not defining a constructor in the `Animal` class, because you specify a return type (`void`). – Joachim Sauer Jan 25 '11 at 14:12
  • 4
    This wouldn't compile - a constructor is *required* in `Cat` because `Animal` has a (not-default) constructor (`public void Animal(String name)` is not a constructor anyway) – Andreas Dolk Jan 25 '11 at 14:14
  • This would only work with a no-arg constructor. Try it, your code won't compile. But the implicit default constructor will always have the visibility of the class itself, regardless of what the superclass constructor's is. – biziclop Jan 25 '11 at 14:22
  • I thought it might not work in java, that is why I specified that I used it in PHP (where you can do mostly any "bright" idea). – Catalin Marin Jan 25 '11 at 15:44
  • 6
    -1, This is also not valid PHP syntax, and the question was tagged Java – Kenny Cason Apr 01 '13 at 19:40