Initialize several static attributes of several classes from one place (Java) - java

I have several class (Sub1, Sub2, Sub3) that inherit all from an abstract class (Abs). All the Sub classes have several properties (size, delay, etc.) that are the same for all instances (like a static attribute). I would like to regroup all these subclasses attributes (and accessors) to avoid duplication of code and initialize it from only one place. Is it possible?
Here is a sample of code that show what I am forced to do to obtain the desired behavior:
public abstract class Abs {
protected static final int DEFALUT_SIZE = 1000;
protected static final int DEFALUT_DELAY = 1000;
}
class Sub1 extends Abs {
private static int size;
private static int delay;
public Sub1() {
size = DEFALUT_SIZE;
delay = DEFALUT_DELAY;
}
public void setSize(int size) { this.size = size; }
public int getSize() { return size; }
public void setDelay(int delay) { this.delay = delay; }
public int getDelay() { return delay; }
}
class Sub2 extends Abs {
private static int size;
private static int delay;
public Sub1() {
size = DEFALUT_SIZE;
delay = DEFALUT_DELAY;
}
public void setSize(int size) { this.size = size; }
public int getSize() { return size; }
public void setDelay(int delay) { this.delay = delay; }
public int getDelay() { return delay; }
}
class Sub3 extends Abs {
/* Same code here */
}
I would like to do the following:
Sub1 sub1 = new Sub1();
int size = Sub1.getSize(); // size == 1000
Sub1.setSize(500);
Sub2.setSize(700);
size = sub1.getSize(); // size == 500
size = Sub1.getSize(); // size == 500
size = Sub2.getSize(); // size == 700
With this solution, I am forced to rewrite all the same code in each subclasses.
I learned that the static attributes were not inherited, so impossible to do so from the abstract class...

It's generally a good idea to assume that, in all cases except constants, the keyword static is evil and should be avoided at all costs.
If you removed the static keyword from in front of size and delay, made them protected, and moved them into the abstract Abs class along with the initialisation code to set their initial values and the accessors and mutators (getters and setters), then you'd be able to remove their declarations and initialisation from the subclasses.
Your code should look something like this:
public abstract class Abs {
private static final int DEFALUT_SIZE = 1000;
private static final int DEFALUT_DELAY = 1000;
private int size = DEFAULT_SIZE;
private int delay = DEFAULT_DELAY;
public void setSize(int size) { this.size = size; }
public int getSize() { return size; }
public void setDelay(int delay) { this.delay = delay; }
public int getDelay() { return delay; }
}
Then anything that extends the Abs class will have these properties.
To share these properties between objects you'll have to do something a little different though, but there are many options. You can have a common class that holds the shared values that is injected into each instance at creation, or you can use some sort of eventing/observer pattern. However, this is quite an odd thing to want in the first place. Typically we'd have some sort of central object representing this information and just pass that around as needed -- you wouldn't typically have setters and getters on subclasses to implement this. What you have is akin to a service managing global properties.

Related

How to make a Constructor without parameters?

I have to write a program that has a constructor without parameters. I created another short program as an example to show what I do not understand.
So I have a class with the main-method:
public class Dog {
public static void main(String[] args) {
CharacteristicsOfTheDog Dog1 = new CharacteristicsOfTheDog(20, 40);
System.out.println(Dog1.toString());
}
}
Now implemented another class:
public class CharacteristicsOfTheDog {
int size = 0;
int kilogram = 0;
public CharacteristicsOfTheDog(/*int size, int kilogram*/) {
// this.size = size;
// this.kilogram = kilogram;
}
public double getSize() {
return size;
}
public double getKilogram() {
return kilogram;
}
public String toString() {
return "The Dog is " + getSize() + " cm and " + getKilogram() + " kg";
}
}
In the class "CharacteristicsOfTheDog" in "public CharacteristicsOfTheDog()" I removed the parameters by commenting them out. So the Problem is: if I remove the parameters the program does not work:/ but my task is to do this without the parameters (as far as I understood). Can someone help me please?
Keep your no-arg constructor and then add setters for your properties:
public class CharacteristicsOfTheDog {
int size = 0;
int kilogram = 0;
public CharacteristicsOfTheDog() {
}
public void setSize(int size){
this.size = size;
}
public void setKilogram(int kilogram){
this.kilogram = kilogram;
}
}
In your other class, call:
CharacteristicsOfTheDog dog1 = new CharacteristicsOfTheDog();
dog.setSize(20);
dog.setKilogram(40);
As a suggestion, the naming of your class as CharacteristicsOfTheDog is rather literal and stating the obvious. Properties and methods of a class are what describes the characteristics of a class in terms of it's properties and behavior. If you just name your class Dog, that would be perfect. No need to state the obvious.
Unless CharacteristicsOfTheDog is a subclass or you have a constructor with parameters, you don't need an empty constructor. Just omit it. The following works just fine.
If the parent class has a constructor with arguments, then the parent class will need an explicit empty constructor, but the following should still work.
CharacteristicsOfTheDog cotd = new CharacteristicsOfTheDog();
cotd.setKilogram(100);
}
class CharacteristicsOfTheDog {
int size = 0;
int kilogram = 0;
public void setSize(int size){
this.size = size;
}
public void setKilogram(int kilogram){
this.kilogram = kilogram;
}
}
Depending on your use case, you might want to make the Characteristics class an interface and implement it.

Java: How to code for items to inherit raw materials' properties?

I am a Java beginner. My problem is, for example:
Fire: DMG +1
Stone: DEF +1
By combining to:
Fire-stone: fire + stone, and inherit both their properties (DMG 1, DEF 1).
Flame: fire + fire, and inherit 2 fire properties (DMG +2).
I've played around with classes and interfaces but doesn't seem to work. It seems to me that Java doesn't support multiple inheritance but multiple interfaces. I wonder how I could code each class/interface for this to work?
public static int DMG, DEF = 0;
public static String DESC = "";
interface fire {
DMG = 1; }
interface stone {
DEF = 1; }
class firestone implements fire, stone {
DESC = "Born in fire and stone";
//DMG and DEF calculations
}
You better use composition, here is what you could do:
public class Main {
public static void main(String[] args) {
Tool firestone = new Tool(new Fire(), new Stone());
}
private static interface Component {
int getDmg();
int getDef();
}
private static class Fire implements Component {
#Override
public int getDmg() {
return 1;
}
#Override
public int getDef() {
return 0;
}
}
private static class Stone implements Component {
#Override
public int getDmg() {
return 0;
}
#Override
public int getDef() {
return 1;
}
}
private static class Tool implements Component {
List<Component> components;
int dmg;
int def;
public Tool(Component... component) {
components = new ArrayList<>();
components.addAll(Arrays.asList(component));
dmg = 0;
def = 0;
for (Component c : components) {
dmg += c.getDmg();
def += c.getDef();
}
}
#Override
public int getDmg() {
return dmg;
}
#Override
public int getDef() {
return def;
}
}}
My implementation may be an overkill :P but it is extendable and you add more components that are more and more complicated.

Inheritance var java

this is the qa:
Define a class called MoreSpeed which extends the following class, and which provides a new method called incSpeed() which adds 1 to the inherited variable length.
this is my answer:
public class Speed {
private int length = 0;
public int getSpeed () { return length; }
public void setSpeed (int i) {
if (i > 0) {
length = i;
}
}
}
public class MoreSpeed extends Speed {
private int length;
public int incSpeed() {
return length+1;
}}
its says that the syntax is good but the class operation is wrong.
please help me,thanks.
No. You are shadowing the length from Speed. Instead, implement incSpeed with getSpeed() like
public int incSpeed() {
return getSpeed() + 1;
}
If you are supposed to modify it as well then use setSpeed(int) to do so
public int incSpeed() {
int s = getSpeed() + 1;
setSpeed(s);
return s;
}

How to construct a method that needs to pass in the values from a constructor?

I'm writing a program that is based around registering the amount of energy consumption that is being used by appliances within a house. So far, I have created various meter classes such as WaterMeter, GasMeter etc. with empty methods that need to be filed with values, I have also created classes for appliances that have methods that will be used to register the consumption of energy within each appliance. What I am working on now is applying the energy values that are stored within a constructor, putting those values into a timePasses() method that will then return those values to their specific meter's methods so that they can be registered. This is what I have so far:
Appliance class example:
public class ElectricShower extends Shower
{
public int isOn = -1;
public int isOff = 0;
public int incrementTime;
public int x = -1;
private static ElectricMeter instance = new ElectricMeter();
public static ElectricMeter getInstance() { return instance; }
#Override
public int currentState()
{
if (x == 0)
return isOff;
else
{
return isOn;
}
//returns isOn;
}
#Override
public void useTime(int defaultTime)
{
defaultTime = 15;
incrementTime = 1;
}
public void shower()
{
//call timePasses() method
}
#Override
public int timePasses()
{
if(x == isOff)
return 0;
else
{
ElectricMeter.getInstance().incrementConsumed(electricityUse);
}
}
ElectricShower(int electricityUse, int gasUse, int waterUse, int timeOn)
{
super(electricityUse, gasUse, waterUse, timeOn);
this.electricityUse = 12 * incrementTime;
this.gasUse = 0 * incrementTime;
this.waterUse = 4 * incrementTime;
this.timeOn = 15 * incrementTime;
}
}
Meter example:
public class ElectricMeter
{
public int incrementConsumed(int value)
{
}
public int incrementGenerated()
{
}
public boolean canGenerate()
{
}
public String getConsumed()
{
}
public String getGenerated()
{
}
}
What I need to do next is:
take the values of electricityUse and waterUse and store them within the timePasses() else staement
Within the timePasses() else statement, place the value of electrcityUse in the incrementGenerated() method within the ElectricMeter class and do the same for the waterUse variable.
UPDATE
Classes have been updated, still struggling to find out how to make it work.
First of all, I assume you have an Appliance class that all the appliances extends from. You should create variables in the Appliance class that stores electricity, gas and water usage:
public class Appliance
{
public int electricityUse, gasUse, waterUse, timeOn;
// ...
}
Note that you should always use getters and setters instead of public fields. I'm just lazy :D
Change your constructor so that the variables above get set:
ElectricShower(int electricityUse, int gasUse, int waterUse, int timeOn)
{
super(electricityUse, gasUse, waterUse, timeOn);
// I don't know why you multiply the constant by incrementTime here. Seems weird. I think you can remove them.
this.electricityUse = 12 * incrementTime;
this.gasUse = 0 * incrementTime;
this.waterUse = 4 * incrementTime;
this.timeOn = 15 * incrementTime;
}
One way to write the else clause is to use the "Singleton Pattern".
In every meter class, write something like this:
private ElectricMeter() {}
private static ElectricMeter instance = new ElectricMeter();
public static ElectricMeter getInstance() { return instance; }
In the incrementConsumed method, you should accept a parameter that indicates how much to increment:
public int incrementConsumed(int value)
{
// logic here...
}
In the else clause, you can just do:
ElectricMeter.getInstance().incrementConsumed(electricityUse);
GasMeter.getInstance().incrementConsumed(gasUse);
WaterMeter.getInstance().incrementConsumed(waterUse);
You should review your design.
If you need to access to a class parameter you could just define it public or better create a so called getter method that returns the value.
Example:
public class MyData {
public int counter;
}
....
// Some other class
MyData data = new MyData();
data.counter = 5;
System.out.println(data.counter);
Or
public class MyData {
private int counter;
public void setCounter(int counter) {
this.counter = counter;
}
public int getCounter() {
return this.counter;
}
}
....
// Some other class
MyData data = new MyData();
data.setCounter(5);
System.out.println(data.getCounter());
In your code I see:
public int incrementConsumed()
{
//Store value of electricityUse.
}
But this method should just return an integer and have not parameter to get an input to store.
It should be:
public void incrementConsumed(int amount) {
this.amount += amount;
}
I'm concerned about this line:
gasUse = 0 * incrementTime;
If you multiply something to 0 it will be always 0...

How to inherit static field and change it's value?

I'm working on program/game where I have static utility class with params.
class ParamsGeneral {
public static final int H_FACTOR = 100;
public static int MAX_SCORE = 1000;
...
}
then I need to override this values in some specific cases, for example playing on map with limited score. So I did following:
class ParamsLimited extends ParamsGeneral {
public static int MAX_SCORE = 500;
// other params stay same
}
And the intended usage is following:
class Player {
ParamsGeneral par;
public Player() {
if(onLimitedMap()){
par = new ParamLimited();
}
}
public boolean isWinner() {
if(this.score == par.MAX_SCORE) {
return true;
}
return false;
}
}
I haven't actually tested this code, because IDE is complaining about calling static field through instance and also about field hiding. I clearly see that this code is stinks, so is there a way to achieve this or do I have to write each param class separately?
PS: I know I shoud make the default class abstract and use getters, I'm just curious if there is a way to make the values accesible statically.
You cannot override static members - in Java, neither methods nor fields could be overriden. However, in this case it does not look like you need to do any of that: since you have an instance of ParamsGeneral in the par variable, a non-static method would do what you need with the regular override.
class ParamsGeneral {
public int getMaxScore() {
return 1000;
}
}
class ParamsLimited extends ParamsGeneral {
#Override public int getMaxScore() {
return 500;
}
}
...
public boolean isWinner() {
// You do not need an "if" statement, because
// the == operator already gives you a boolean:
return this.score == par.getMaxScore();
}
I wouldn't use subclassing for a general game vs a limited game. I would use an enumeration, like:
public enum Scores {
GENERAL (1000),
LIMITED (500),
UNLIMITED (Integer.MAX_INT);
private int score;
private Scores(int score) { this.score = score; }
public int getScore() { return score; }
}
Then, when constructing a game, you can do:
Params generalParams = new Params(Scores.GENERAL);
Params limitedParams = new Params(Scores.LIMITED);
And so forth.
Doing it this way allows you to change the nature of your game while keeping your values centralized. Imagine if for every type of parameter you think of you have to create a new class. It could get very complicated, you could have hundreds of classes!
Simplest solution is to do this:
class ParamsGeneral {
public static final int H_FACTOR = 100;
public static final int MAX_SCORE = 1000;
public static final int MAX_SCORE_LIMITED = 500;
...
}
class Player {
int maxScore;
public Player() {
if(onLimitedMap()){
maxScore = ParamsGeneral.MAX_SCORE_LIMITED;
}
else {
maxScore = ParamsGeneral.MAX_SCORE;
}
}
public boolean isWinner() {
if(this.score == this.maxScore) {
return true;
}
return false;
}
}
No need to have an instance of ParamsGeneral, it is just a collection of static definitions for your game.
Have MAX_SCORE be private static with public static getters; then you can call ParamsGeneral.getMaxScore and ParamsLimited.getMaxScore and you'll get 1000 and 500 respectively

Categories