1

I have a super class 'BuildingMaterial' and loads of subclasses, i.e. Stone, Wood, Clay, etc. All subclasses behave similarly: 1 int field that stores the amount of a building material in units. They can be constructed parameterless or with an int. I already know that ALL subclasses of BuildingMaterial will have these two constructors, how do I avoid coding them into every single class? Here's an example of what I don't want to do in every class:

public final class Stone extends BuildingMaterial {

    private int amount;

    //constructors
    public Stone() {
      amount = 0;
    }

    public Stone(int i) {
      amount = i;
    }

    //methods
    public int getAmount() {
      return amount;
    }
}

5 Answers 5

5

Sadly, the answer is you can't. This is a limitation of the Java language. Each class needs its own constructors—you can't simply inherit them from a parent class. The only constructor the Java compiler will generate for you is the default constructor (no arguments), and it only generates that if you don't specify any constructors at all.

The best you can do here is to refactor your code so amount is in the superclass:

public abstract class BuildingMaterial {

    private int amount;

    //constructors
    public BuildingMaterial() {
      this(0);
    }

    public BuildingMaterial(int i) {
      amount = i;
    }

    //methods
    public int getAmount() {
      return amount;
    }

}

And then make use of super calls to delegate the superclass's constructor in your subclasses:

public final class Stone extends BuildingMaterial {

    //constructors
    public Stone() {
      super();
    }

    public Stone(int i) {
      super(i);
    }

}

Note that I changed the body of your no-argument constructor from amount=0; to this(0);. I personally think this is better style because, if you decide to add other initialization code to your constructor body, you only have to add it to the 1-argument constructor, and the zero-argument constructor will just delegate all the work to it.

Sign up to request clarification or add additional context in comments.

Comments

2

You have to use inheritance

public abstract class BuildingMaterial {
    private int amount;

    //constructors
    public BuildingMaterial() {
        amount = 0;
    }

    public BuildingMaterial(int i) {
        amount = i;
    }

    //methods
    public int getAmount() {
        return amount;
    }
}


public class Stone extends BuildingMaterial {
    public Stone() {
        super();
    }

    public Stone(int i) {
        super(i);
    }
}

This way all subclasses of BuildingMaterial can give access to amount through getters and setters.

You may have amount declared as protected so you wont need getters or setters to access that field inside subclasses.

5 Comments

I'm curious where the necessity arises to make BuildingMaterial abstract in this example?
@user2651804 - It's not *necessary*—it's just good practice. "Building Material" is an abstract concept, so you'd never expect to actually create an instance of the BuildingMaterial class itself (you only create instances of concrete subclasses). By making the class abstract, you communicate this idea and Java will make sure no one ever calls new BuildingMaterial(). Note that I made the same choice (making BuildingMaterial abstract) in my answer.
@user2651804 can a BuildingMaterial be a concrete object? do you ever want to make instances of that class? does it make sense to have such an object? or do only want to have instances of its subclasses?
@user2651804, the same goes for final for the class Stone, making it final will prevent any further specialization, i.e. SomClasse extends Stone. But you may want to have different kinds of Stones represented as subclasses of Stone not only BuildingMaterial.
Alright, I see your points. I will declare BuildingMaterial abstract and Stone final for readability. Thank you all very much for your answers =]
1

use super keyword to reduce your code but the super is to be the first line inside the constructor

public class Stone extends BuildingMaterial {
    public Stone() {
        super();
    }

    public Stone(int i) {
        super(i);
    }
} 

Comments

0

If all classes has the attribute amount, then that attribute can be inherited from parent. Define amount in your parent class BuildingMaterial and then call the parent constructor from your child classes constructors using super to set the amount value.

2 Comments

Yes, I will define amount in the parent class. But I will need to make for instance both: new Stone() and new Stone(50). I don't really understand if you've explained me how I can do this :S
If you want to use the constructors to initialize the object with that value then you need to have such constructor in each child class. But another way can be to have a setAmount method in superclass, and set the amount using that method once the object is created.
0

Its unclear what you want to avoid in your question... assuming you are talking about avoiding writing multiple constructors in all the subclass. I believe its not possible to do so. below post of defining BuildingMeterial constructor and calling the super() from baseClass will be the best solution to use.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.