How to force subclasses to set a variable in java? - java

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;
}
}

Related

Use of Protected Constructor

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.

Call constructor in an abstract class

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

abstract class with default constructor and class with private constructor difference

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...

how to make constructor definition mandatory

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()

Can an abstract class have a constructor?

Can an abstract class have a constructor?
If so, how can it be used and for what purposes?
Yes, an abstract class can have a constructor. Consider this:
abstract class Product {
int multiplyBy;
public Product( int multiplyBy ) {
this.multiplyBy = multiplyBy;
}
public int mutiply(int val) {
return multiplyBy * val;
}
}
class TimesTwo extends Product {
public TimesTwo() {
super(2);
}
}
class TimesWhat extends Product {
public TimesWhat(int what) {
super(what);
}
}
The superclass Product is abstract and has a constructor. The concrete class TimesTwo has a constructor that just hardcodes the value 2. The concrete class TimesWhat has a constructor that allows the caller to specify the value.
Abstract constructors will frequently be used to enforce class constraints or invariants such as the minimum fields required to setup the class.
NOTE: As there is no default (or no-arg) constructor in the parent
abstract class, the constructor used in subclass must explicitly call
the parent constructor.
You would define a constructor in an abstract class if you are in one of these situations:
you want to perform some
initialization (to fields of the
abstract class) before the
instantiation of a subclass actually
takes place
you have defined final fields in the
abstract class but you did not
initialize them in the declaration
itself; in this case, you MUST have
a constructor to initialize these
fields
Note that:
you may define more than one
constructor (with different
arguments)
you can (should?) define all your
constructors protected (making them
public is pointless anyway)
your subclass constructor(s) can
call one constructor of the abstract
class; it may even have to call it
(if there is no no-arg constructor
in the abstract class)
In any case, don't forget that if you don't define a constructor, then the compiler will automatically generate one for you (this one is public, has no argument, and does nothing).
Yes it can have a constructor and it is defined and behaves just like any other class's constructor. Except that abstract classes can't be directly instantiated, only extended, so the use is therefore always from a subclass's constructor.
Yes! Abstract classes can have constructors!
Yes, when we define a class to be an Abstract Class it cannot be instantiated but that does not mean an Abstract class cannot have a constructor. Each abstract class must have a concrete subclass which will implement the abstract methods of that abstract class.
When we create an object of any subclass all the constructors in the corresponding inheritance tree are invoked in the top to bottom approach. The same case applies to abstract classes. Though we cannot create an object of an abstract class, when we create an object of a class which is concrete and subclass of the abstract class, the constructor of the abstract class is automatically invoked. Hence we can have a constructor in abstract classes.
Note: A non-abstract class cannot have abstract methods but an abstract class can have a non-abstract method. Reason is similar to that of constructors, difference being instead of getting invoked automatically we can call super(). Also, there is nothing like an abstract constructor as it makes no sense at all.
Not only can it, it always does. If you do not specify one then it has a default no arg constructor, just like any other class. In fact, ALL classes, including nested and anonymous classes, will get a default constructor if one is not specified (in the case of anonymous classes it is impossible to specify one, so you will always get the default constructor).
A good example of an abstract class having a constructor is the Calendar class. You get a Calendar object by calling Calendar.getInstance(), but it also has constructors which are protected. The reason its constructors are protected is so that only its subclasses can call them (or classes in the same package, but since it's abstract, that doesn't apply). GregorianCalendar is an example of a class that extends Calendar.
Although there are many good answers, I would like to give my 2 cents.
Constructor DOES NOT BUILD THE OBJECT. It is used to initialize an object.
Yes, an Abstract class always has a constructor. If you do not define your own constructor, the compiler will give a default constructor to the Abstract class.
Above holds true for all classes - nested, abstract, anonymous, etc.
An abstract class (unlike interface) can have non-final non-static fields which need initialization. You can write your own constructor in the abstract class to do that. But, in that case, there won't be any default constructor.
public abstract class Abs{
int i;
int j;
public Abs(int i,int j){
this.i = i;
this.j = j;
System.out.println(i+" "+j);
}
}
Be careful while extending above abstract class, you have to explicitly call super from each constructor. The first line of any constructor calls to super(). if you do not explicitly call super(), Java will do that for you.
Below code will not compile:
public class Imp extends Abs{
public Imp(int i, int j,int k, int l){
System.out.println("2 arg");
}
}
You have to use it like below example:
public class Imp extends Abs{
public Imp(int i, int j,int k, int l){
super(i,j);
System.out.println("2 arg");
}
}
An abstract class can have a constructor BUT you can not create an object of abstract class so how do you use that constructor?
Thing is when you inherit that abstract class in your subclass you can pass values to its(abstract's) constructor through super(value) method in your subclass and no you don't inherit a constructor.
so using super you can pass values in a constructor of the abstract class and as far as I remember it has to be the first statement in your method or constructor.
Yes it can, abstract classes constructors are generally used for super calls for initialization events common to all the subclasses
Of Course, abstract class can have a constructor.Generally class constructor is used to initialise fields.So, an abstract class constructor is used to initialise fields of the abstract class. You would provide a constructor for an abstract class if you want to initialise certain fields of the abstract class before the instantiation of a child-class takes place. An abstract class constructor can also be used to execute code that is relevant for every child class. This prevents code duplication.
We cannot create an instance of an abstract class,But we can create instances of classes those are derived from the abstract class. So, when an instance of derived class is created, the parent abstract class constructor is automatically called.
Reference :This Article
Yes, Abstract Classes can have constructors !
Here is an example using constructor in abstract class:
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
// area is now an abstract method
abstract double area();
}
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b);
}
// override area for rectangle
double area() {
System.out.println("Inside Area for Rectangle.");
return dim1 * dim2;
}
}
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
// override area for right triangle
double area() {
System.out.println("Inside Area for Triangle.");
return dim1 * dim2 / 2;
}
}
class AbstractAreas {
public static void main(String args[]) {
// Figure f = new Figure(10, 10); // illegal now
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
Figure figref; // this is OK, no object is created
figref = r;
System.out.println("Area is " + figref.area());
figref = t;
System.out.println("Area is " + figref.area());
}
}
So I think you got the answer.
As described by javafuns here, this is an example:
public abstract class TestEngine
{
private String engineId;
private String engineName;
public TestEngine(String engineId , String engineName)
{
this.engineId = engineId;
this.engineName = engineName;
}
//public gettors and settors
public abstract void scheduleTest();
}
public class JavaTestEngine extends TestEngine
{
private String typeName;
public JavaTestEngine(String engineId , String engineName , String typeName)
{
super(engineId , engineName);
this.typeName = typeName;
}
public void scheduleTest()
{
//do Stuff
}
}
In a concrete class, declaration of a constructor for a concrete type Fnord effectively exposes two things:
A means by which code can request the creation of an instance of Fnord
A means by which an instance of a type derived from Fnord which is under construction can request that all base-class features be initialized.
While there should perhaps be a means by which these two abilities could be controlled separately, for every concrete type one definition will enable both. Although the first ability is not meaningful for an abstract class, the second ability is just as meaningful for an abstract class as it would be for any other, and thus its declaration is just as necessary and useful.
Abstract class can have a constructor though it cannot be instantiated. But the constructor defined in an abstract class can be used for instantiation of concrete class of this abstract class. Check JLS:
It is a compile-time error if an attempt is made to create an instance of an abstract class using a class instance creation
expression.
A subclass of an abstract class that is not itself abstract may be
instantiated, resulting in the execution of a constructor for the
abstract class and, therefore, the execution of the field initializers
for instance variables of that class.
yes it is. And a constructor of abstract class is called when an instance of a inherited class is created. For example, the following is a valid Java program.
// An abstract class with constructor
abstract class Base {
Base() { System.out.println("Base Constructor Called"); }
abstract void fun();
}
class Derived extends Base {
Derived() { System.out.println("Derived Constructor Called"); }
void fun() { System.out.println("Derived fun() called"); }
}
class Main {
public static void main(String args[]) {
Derived d = new Derived();
}
}
This is the output of the above code,
Base Constructor Called
Derived Constructor Called
references:
enter link description here
Consider this:
abstract class Product {
int value;
public Product( int val ) {
value= val;
}
abstract public int multiply();
}
class TimesTwo extends Product {
public int mutiply() {
return value * 2;
}
}
The superclass is abstract and has a constructor.
Yes surely you can add one, as already mentioned for initialization of Abstract class variables.
BUT if you dont explicitly declare one, it anyways has an implicit constructor for "Constructor Chaining" to work.
Since an abstract class can have variables of all access modifiers, they have to be initialized to default values, so constructor is necessary.
As you instantiate the child class, a constructor of an abstract class is invoked and variables are initialized.
On the contrary, an interface does contain only constant variables means they are already initialized. So interface doesn't need a constructor.
In order to achieve constructor chaining, the abstract class will have a constructor.
The compiler keeps Super() statement inside the subclass constructor, which will call the superclass constructor. If there were no constructors for abstract classes then java rules are violated and we can't achieve constructor chaining.
Yes, an Abstract Class can have a Constructor. You Can Overload as many Constructor as you want in an Abstract Class. These Contractors Can be used to Initialized the initial state of the Objects Extending the Abstract Class. As we know we can't make an object of an Abstract Class because Objects are Created by the "new" keywords and not by the constructors...they are there for only initializing the state of the subclass Objects.
The purpose of the constructor in a class is used to initialize fields but not to "build objects". When you try to create a new instance of an abstract SuperClass, the compiler will give you an error. However, we can inherit an abstract class Employee and make use of its constructor by setting its variables See example below
public abstract class Employee {
private String EmpName;
abstract double calcSalary();
Employee(String name) {
this.EmpName = name;// constructor of abstract class super class
}
}
class Manager extends Employee{
Manager(String name) {
super(name);// setting the name in the constructor of sub class
}
double calcSalary() {
return 0;
}
}
package Test1;
public class AbstractClassConstructor {
public AbstractClassConstructor() {
}
public static void main(String args[]) {
Demo obj = new Test("Test of code has started");
obj.test1();
}
}
abstract class Demo{
protected final String demoValue;
public Demo(String testName){
this.demoValue = testName;
}
public abstract boolean test1();
}
class Test extends Demo{
public Test(String name){
super(name);
}
#Override
public boolean test1() {
System.out.println( this.demoValue + " Demo test started");
return true;
}
}
Yes..It is like any other class. It can have a constructor and it is called after creating object for the base class.

Categories