Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any point in an abstract class having public constructor instead of protected one?

Since an abstract class cannot be instantiated, and since protected members are always visible to subclasses, it would seem that it makes no difference whether its constructors are public or protected.

Is there any example where a public constructor could make a difference compared to a protected one? I would normally prefer the most restrictive access level which is applicable.

like image 748
William F. Jameson Avatar asked Oct 27 '14 20:10

William F. Jameson


People also ask

Should abstract class have public constructor?

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.

Should abstract class constructor be protected?

After all, an abstract class cannot be created directly – only via a derived instance. Consequently, it is only the derived classes for whom it makes sense to access the constructor in the first place. Hence, ReSharper recommends that you make the constructor protected .

Should an abstract class be public?

Abstract classes shouldn't have public constructors because they don't make sense. Abstract classes are incomplete, so allowing a public constructor (which anyone could call) wouldn't work as you can't instantiate an instance anyway.

Can we use public with abstract class?

Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.


1 Answers

No, there is no good reason to make a public constructor for an abstract class: you cannot instantiate your abstract class without subclassing it first, and the language deals with the relevant corner cases for you.

In particular, if you are to subclass your abstract class anonymously, meaning that you are unable to provide your own constructor in the subclass, the language would provide one for you based on the signature of the protected constructor of your abstract base class:

abstract class Foo {
    protected int x;
    protected Foo(int x) {this.x = x;}
    public abstract void bar();
}
public static void main (String[] args) {
    Foo foo = new Foo(123) { // <<== This works because of "compiler magic"
        public void bar() {System.out.println("hi "+x);}
    };
    foo.bar();
}

In the example above it looks like the protected constructor of an abstract class is invoked, but that is not so: the compiler builds a visible constructor for your anonymous class*, which is what gets invoked when you write new Foo(123).

Demo.

* The actual visibility is default. Thanks, Pshemo, for spotting the error and supplying a nice test example.

like image 169
Sergey Kalinichenko Avatar answered Nov 05 '22 19:11

Sergey Kalinichenko