We usually create public constructor and for singletone reason create the private constructor, so I was wondering if what is the use of protected constructor.
A sub-class of an abstract class would need to call the constructor of its super class, so a protected constructor would make sense.
public abstract class A
{
protected A (int something)
{
}
}
public class B extends A
{
public B (int something)
{
super(something);
}
}
Actually, in case of an abstract super-class, you don't need the constructor to be protected, since you can't create an instance of A even if the constructor was public. But even if A is not abstract, you might want to define a constructor of A that can only be invoked by sub-classes of A.
Related
Is it possible to call a constructor in a abstract class?
I read that this constructor can be called through one of its non-abstract subclasses. But I don't understand that statement. Can anybody explain this with an example?
You can define a constructor in an abstract class, but you can't construct that object. However, concrete sub-classes can (and must) call one of the constructors defined in the abstract parent class.
Consider the following code example:
public abstract class Test {
// abstract class constructor
public Test() {
System.out.println("foo");
}
// concrete sub class
public static class SubTest extends Test {
// no constructor defined, but implicitly calls no-arg constructor
// from parent class
}
public static void main(String[] args) throws Exception {
Test foo = new Test(); // Not allowed (compiler error)
SubTest bar = new SubTest(); // allowed, prints "foo"
}
}
You can't call an abstract class constructor with a class instance creation expression, i.e.
// Invalid
AbstractClass x = new AbstractClass(...);
However, in constructing an object you always go through the constructors of the whole inheritance hierarchy. So a constructor from a subclass can call the constructor of its abstract superclass using super(...). For example:
public class Abstract {
protected Abstract(int x) {
}
}
public class Concrete {
public Concrete(int x, int y) {
super(x); // Call the superclass constructor
}
}
As constructors of abstract classes can only be called within subclass constructors (and by chaining one to another within the same class), I typically make them protected... making them public would serve no purpose.
The normal rules apply if you don't specify a super(...) or this(...) call in a concrete subclass constructor - it's equivalent to a super(); statement at the start of a constructor, calling a parameterless constructor in the superclass... so there'd have to be such a constructor.
In this example Java program, we have an abstract class Servidor, which has one parametric constructor, which accepts name. Subclass provides that name to superclass while creating concrete instance of Servidor and overriding abstract method start(). Since this program compile and run fine you can definitely say abstract class can have constructors in Java.
public class AbstractConstructorTest {
public static void main(String args[]) {
Servidor Servidor = new Tomcat("Apache Tomcat");
Servidor.start();
}
}
abstract class Servidor{
protected final String name;
public Servidor(String name){
this.name = name;
}
public abstract boolean start();
}
class Tomcat extends Servidor{
public Tomcat(String name){
super(name);
}
#Override
public boolean start() {
System.out.println( this.name + " started successfully");
return true;
}
}
Output:
Apache Tomcat started successfully
You can obviously do something like:
public class ConcreteClass extends AbstractClass {
public ConcreteClass(){ // concrete class constructor
super(); // abstract class constructor
}
}
A constructor of an abstract class can be used only inside constructors of concrete classes inheriting from it.
Abstract and Concrete classes are something like Generalization and Specialization in Java and can be executed using inheritance. Let me explain with a plain and simple example. Say we have a class "DBConnector". It seems to be more generalized class and its meaning less to instantiate the class (which DB you are connecting to, driver vary for each DB right). Hence we can make DBConnector as abstract. That is the reason why we cannot basically instantiate Abstract classes.
Now we can create different concrete classes for each database extending the behavior of our concrete class like "OracelDBConnector", "MySQLDBConnector" etc., As we inherit the properties of abstract class into concrete class, we initialize the abstract class properties ideally using abstract class constructor using concrete class constructor using super(parameter list).
Thanks,
JK
what's the difference between an Abstract class with a default constructor and a class with private constructor?
I also have another doubt ,
consider this program below. Can anyone please explain me.Does such code have any use ?
abstract class AbstractAndPrivate
{
AbstractAndPrivate()
{
AbstractAndPrivate ref= new AbstractAndPrivate(1) {
#Override
int m2() {
// TODO Auto-generated method stub
return 0;
}
};
}
void m1()
{
System.out.println("m1() accessed");
}
abstract int m2();
AbstractAndPrivate(int a)
{
}
public static void main(String[] args) {
System.out.print("hello ");
AbstractAndPrivate ref= new AbstractAndPrivate() {public int m2(){return 1;}};
System.out.println(ref);
ref.m1();
ref.m2();
}
}
what's the difference between an Abstract class with a default constructor and a class with private constructor?
If there's a default constructor, it will be callable from subclasses. If it's private, you'll only be able to create subclasses within the same class, as that's the only context in which the private constructor will be accessible.
Note that the code you've provided is neither of these situations - it's explicitly providing a package-protected parameterless constructor. That's not private, and it's not a default constructor.
Whether the class is abstract or not is orthogonal to the constructors it provides, although an abstract class with only a private constructor forces you to create subclasses within the declaring class in order to create instances, rather than just relying on you creating instances within the declaring class.
also, abstract class can have an abstract method, that needs to be implemented by subclasses (unless they're abstract too)
EDIT: -1? come on, abstract methods are also sort of explains the logical difference between abstract classes and classes with private constructor. please...
I have a class which defines all of the basic parameters for a given screen. From here every screen in the application is a subclass of this. I need every screen (i.e. subclass) to set the value of a variable in its implementation (namely, each screen must define what level it is in a navigation tree).
Also, ideally, this variable should be final when it is set in the sub classes (I realise this probably isn't possible).
What is the best way to go about this? Is there a way to correctly enforce this type of behaviour in Java?
#pst's comment lead to this solution.
This can't be done with a variable. But an abstract class can require that a particular method is implemented: this method could return the applicable value
From declaring an abstract function to set or return the variable, you can force any subclass to implement it correctly.
Next, the function must be called by every single subclass of the outer class. This implies that it must be done somewhere in the outer class. This can be done in the no-argument constructor of the outer class without having to worry about subclasses calling super:
Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
(Java docs: Super)
Based on that, this solution will hold up and correctly force the variable to be set as long as either:
No other constructor is created in the superclass (hence super can't be used in a subclass to call a different constructor instead)
All other constructors in the superclass still call the default constructor internally
The code:
Superclass:
public abstract class SuperClass {
// Variable all inner classes must set
static int myVar = 0;
public SuperClass() {
myVar = giveValue();
}
public abstract int giveValue();
}
Subclass:
public class SubClass extends SuperClass {
#Override
public int giveValue() {
return 5; // individual value for the subclass
}
}
Rather than enforce that child class instances initialize the fields, you could follow a strategy of composition by having your parent class constructor take a parameter implementing an interface that provides the fields you wish to have initialized.
class Screen {
final Configuration config;
Screen(Configuration config) {
this.config = config;
}
// or
Screen(ConfigFactory configFactory) {
this.config = configFactory.make();
}
}
interface ConfigFactory {
Configuration make();
}
I would caution against requiring a subclass instance initializing the configuration, say using an abstract method implementation. The assignment in the parent class constructor occurs before the subclass instance is initialized, implicitly making proper computation of the configuration static.
If the computation isn't static, you risk null references or NullPointerExceptions by developers following you (or yourself if your memory is less than perfect). Make it easier on your collaborators (and yourself) and make the constraints explicit.
As mentioned by #Ketan in #B T's answer, invoking an overridable method from constructor is not especially a good practice (https://help.semmle.com/wiki/display/JAVA/Non-final+method+invocation+in+constructor)
One way to avoid this problem consists in having an abstract (protected) getter for the field. Hence the superclass doesn't have the field anymore, but it is still accessible in the super class using the getter. Each subclass is forced to declare the field because it must override the abstract getter.
Superclass:
public abstract class SuperClass {
public SuperClass() {}
protected abstract int getMyVar();
public void functionUsingMyVar(){
int a = 12 + getMyVar();
}
}
Subclass1:
public class SubClass1 extends SuperClass {
private int myVar;
public SubClass1() {
super();
myVar = 1;
}
#Override
protected int getMyVar(){
return myVar;
}
}
Subclass2:
public class SubClass2 extends SuperClass {
private int myVar;
public SubClass2() {
super();
myVar = 1;
}
#Override
protected int getMyVar(){
return myVar;
}
}
instead of having for the superclass (where giveValue() is overridable and called in the constructor) :
public abstract class SuperClass {
private int myVar;
public SuperClass() {
myVar = giveValue();
}
protected abstract int giveValue();
public void functionUsingMyVar(){
int a = 12 + myVar;
}
}
I created an abstract base class. It contains an object which should be extended by any subclasses:
public abstract class AbstractParent {
protected AbstractObject subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract AbstractObject createThisInYourExtendedClass();
}
the abstractObject:
public abstract class AbstractObject {
// ... some fields/methods that all subclasses need
}
What I want is to be able to use the extended field in the extended class without casting:
public class ExtendParent extends AbstractParent {
// .. some unique fields
public ExtendParent(){
super();
}
public ConcreteObject createThisInYourExtendedClass(){
return new ConcreteObject();
}
// what I want to do - no cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(this.subMePlz);
}
// what I end up doing - gotta cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println((ConcreteObject)this.subMePlz);
}
}
Would needing a comparator change how I should implement this? - I'm thinking a generic comparator for a list of the AbstractObjects that could be used by its subclasses.
It sounds like you need to make it generic:
public abstract class AbstractParent<T extends AbstractObject> {
protected T subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract T createThisInYourExtendedClass();
}
public class ExtendParent extends AbstractParent<ConcreteObject> {
...
}
Note that calling non-private methods within a constructor is usually a bad idea - the subclass won't have been fully initialized yet, which can make it difficult to reason about how much you can really rely on.
You have two options:
Abandon the project to declare the field in the superclass. Instead, add an internal abstract "getter" method to your superclass -- basically, AbstractParent should have a method abstract AbstractObject getSubMePlz().
Use generics to set the type of subMePlz in your subclass: define AbstractParent<T> to have a T for its subMePlz field.
Personally, I frequently find option 1 to be very pleasantly extensible -- for example, you can have another subclass that narrows the getSubMePlz() return type without yet declaring it, which can be advantageous.
Why not use this -
super.subMePlz
instead of this -
(ConcreteObject)this.subMePlz
That way, you won't need a cast.
You just could save a copy of the object in the subclass but with the correct class.
public class ExtendParent extends AbstractParent {
ConcreteObject concreteObject;
public AbstractObject createThisInYourExtendedClass(){
ConcreteObject concreteObject = new ConcreteObject();
return concreteObject;
}
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(concreteObject);
}
...
I have an interface I that is implemented by a base class B. The base class is extended by a bunch of classes (A,C,D) that must init some of the protected vars declared in base class B. I'd like to make the declaration of a constructor mandatory in the subclasses (A,C,D), to discourage the user from relying on default constructor that's declared in B. Yet I do want the B's default constructor to execute automatically, since B can be used by itself as well. How can I accomplish this?
thanks
Use an abstract superclass of B with a private constructor:
public abstract class BSuper {
private BSuper() {
// initialize stuff
}
protected BSuper(some params) {
this():
// other init with parms
}
}
public class B extends BSuper {
public B(some other params) {
super(some params);
}
}
public class A extends B {
public A() {
super(some other params);
}
}
or similar
Make B's default constructor private and call this(); from within the parameterized constructor...
public class B {
private B() {
super();
}
public B( Foo foo ) {
this();
}
public static B createInstance() {
return new B();
}
}
Edit: Miss read the issue, removed abstract keyword from class declaration. Also added public static factory method for creating B class. It calls B's default constructor.
Just write a comment in the Javadoc that says "Use of default constructor is discouraged when subclassing." In my experience, trying to enforce that programmatically is not worth the effort and could cause problems latter on. Simple English will do.
If class B is going to have its own default constructor, what you want is impossible. When you derive from a class, you're telling the compiler that it should allocate memory for a base class object in every instance of the derived class. There's no way to tell a java compiler to suddenly take away some of the base class's functionality every time that something is inherited from it.
Also note that constructors and static factory methods can't be abstract, so even if B could be an abstract class you would have to do something like:
public class B {
B() {
initialize();
}
protected abstract void initialize();
}
...along with making sure that the derived classes implement default constructors that call super()