Best way to store templated constants in Java - java

I have 4 motors let's say, and for each, I have some constants like the ID, the maximum speed, and the minimum power. Let's say that at some point there are going to be many constants added to this MotorConstants class, and this is what it currently looks like:
public abstract class MotorConstants{
abstract final int ID;
abstract final double MAX_SPEED, MIN_POWER;
}
// And an implementation:
public class LeftMotorConstants extends MotorConstants{
final int ID = 3;
final double MAX_SPEED = 500, MIN_POWER = 10;
}
I understand that abstract fields are not possible. What could be a good replacement for them?
I'm afraid of passing everything through the constructor/getters and setters because then after adding a field would take a lot of time and lots of lines of code, instead of the (not working) code sample.

Constants cannot be inherited and then overwritten; that defeats the purpose of calling them "constant. Methods can be overridden to return differing values (even if they return an external constant variable).
If I understand your data model, and ID belongs to a specific instance of some "part". The other fields are also specific properties to some instance, which should not belong to the overall class, so that would be done with methods.
This is where you'd use interfaces to define those common "templates" that a class needs to implement.
E.g.
interface LimitedPower {
double getMinPower();
}
interface LimitedSpeed {
double getMaxSpeed();
}
interface Identifiable {
int getId();
}
abstract class AbstractMotor implements Identifiable {
protected int id; // available to all subclasses
#Override
public int getId() {
return this.id;
}
}
class LimitedMotor extends AbstractMotor implements LimitedSpeed, LimitedPower {
private double minPower, maxSpeed;
public LimitedMotor(int id, double minPower, double maxSpeed) {
this.id = id;
this.minPower = minPower;
this.maxSpeed = maxSpeed;
}
// TODO: implement interface getter+setter functions
}
class MotorPowered {
final AbstractMotor[] motors = new AbstractMotor[4];
public MotorPowered(AbstractMotor left, AbstractMotor right, AbstractMotor top, AbstractMotor buttom) {
this.motors[0] = left;
//... etc
}
}
Then, when you actually create a specific motor, you can pass in the details for it.
final AbstractMotor left = new LimitedMotor(3, 10, 500);
MotorPowered engine = new MotorPowered(left, ...);
If you want to say "all 'limited motors' will have the same id", then you can add some final static int ID to that class, and remove the constructor parameter.
class LimitedMotor extends AbstractMotor implements LimitedSpeed, LimitedPower {
private double minPower, maxSpeed;
public static final int ID = 3;
public LimitedMotor(double minPower, double maxSpeed) {
this.id = LimitedMotor.ID;
this.minPower = minPower;
this.maxSpeed = maxSpeed;
}

Related

How to create an object while using enum in a class?

I previously have the variable availability stored in a double which is present inside a class named wrapper as below -
public final class Wrapper {
private final double availability;
Wrapper(){
this.availability = 2;
}
public Wrapper(final double availability){
this.availability = availability;
}
public double availability (){ // Need a confirmation if this is a getter ?
return this.availability;
}
}
Now, I have to change the scenario a bit by making availability as an object.Reason being - Now we want availability per region unlike the above case.Also, we need to use that availability object inside the wrapper class now.
Here is what I'm trying to do -
public final class Availability {
public enum Region {
US,
UK,
EU;
private final double availability;
Region () {
this.availability = 2;
}
Region (double availability) {
this.availability = availability ;
}
}
I'm supposed to use the Availability object inside wrapper class as wrapper class object is being used in other places which previously used to take argument (Availability). Now I don't want to break that workflow. Also I'm a bit confused a bit regarding creation of object for Availability class as I'm using an enum. Can anyone please help me with this. Thanks in advance!
Per my understanding, you do not need class Availability.
Define Region.java file as having public enum Region, then you can have that constructor along with adding a missing getter.
public enum Region {
US(2),
UK(2),
EU(2);
private final double availability;
Region (double availability) {
this.availability = availability ;
}
public getAvailability() {
return this.availability;
}
}
Then Wrapper can accept Region instance instead, and access .getAvailability() method of it.
public final class Wrapper {
private final Region region;
public Wrapper(Region region){
this.region = region;
}
public double getAvailability() {
return this.region.getAvailability();
}
e.g. System.out.print(new Wrapper(Region.US).getAvailability());

Constructor Chaining with subclasses in Java

Just a question RE: Constructor Chaining in subclasses that I can't find a good answer on and I'm confusing myself a bit with.
I'm making a basic little Text Based RPG for some practice and I'm going through my constructors for an abstract class and have the constructors from 0-4 params chained together like below
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
// Constructors + Chaining
public Creature() {
this("Unknown")
}
public Creature(String name) {
this(name, 100);
}
public Creature(String name, int lifeForce) {
this(name, lifeForce, 10);
}
public Creature(String name, int lifeForce, int strength) {
this(name, lifeForce, strength, 10);
}
public Creature(String name, int lifeForce, int strength, int agility) {
this.name = name;
this.lifeForce = lifeForce;
this.strength = strength;
this.agility = agility;
}
My confusion is how best to format the constructors of a subclass of creature, for example this simple Person class introduces two new fields. There's definitely too much repetition if I write the constructors like this
// Constructors + Chaining
public Person() {
super("Unknown");
this.skillClass=new Mage();
this.dialogue="...";
}
public Person(String name) {
super(name);
this.skillClass=new Mage();
this.dialogue="...";
} etc etc etc
I suppose I could restrict the constructors to limit the repetition but I'm mostly just wondering if there's good best practice that I'm missing here.
Any and all suggestions welcome and if anyone has any good resources to recommend that go deeper than the usual
Class B extends Class A
examples I'd massively appreciate.
In situations like this one when you need to use multiple constructors with different parameters, it is recommended to use the builder pattern like this :
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
private Creature(Builder<?> builder) {
this.name = builder.name;
this.lifeForce = builder.lifeForce;
// Add the other attributes here.
}
public static abstract Builder extends Builder<T extends Builder<T>> {
private String name;
private int lifeForce;
private int strength;
private int agility;
public Builder(//here you put the attributes that you need to have in all instances) {
// here you do the affectations.
}
// now you need to make the functions that set each property :
public Builder lifeForce(int lifeForce) {
this.lifeForce = lifeForce;
return this;
}
// you do the same thing for all the other attributes.
...
public Creature build() {
return new Creature(this);
}
}
}
So for the explanation : This pattern will allow you to create instances of your class by setting only the needed attributes.
As here you have subclasses the builder pattern will be little bit more harder to understand but it is the perfect solution in such situation.
We need to apply the builder pattern also for every subclasse so let's do it for the person class :
public class Person extends Creature {
private int anotherField;
public Person(Builder builder) {
super(builder);
this.anotherField = anotherField;
}
public static Builder extends Creature.Builder<Builder> {
public Builder(//add the fieldHere if it is needed in all class instances) {
// if the field is not mandatory you can omit this constructor but you need to put the function below.
}
public Builder anotherField(int anotherField) {
this.anotherField = anotherField;
}
public Person build() {
return new Person(this);
}
}
Now let me show you how tricky is this solution :
1/ declare person with 2 fields :
Person p1 = Person.Builder().name("name").anotherField(0).build();
2/ declare another one with just one field
Person p2 = Person.Builder().agility(1000).build();
Remark : In these two examples, i supposed that your builders' constructors don't have parameters. If for example the name is mandatory field :
Person p3 = Person.Builder("name").anotherField(0).build();
I wish that you had the idea about using builder pattern.

modeling a inheritance hierarchy... java

Lodgings in Oshkosh can be classified into three kinds – Hotels (modeled by the number of rooms and star rating), Hostels (modeled by the number of rooms and whether bike rentals are available), and Bed-n-Breakfasts (modeled by the number of rooms and whether late arrivals are allowed). Rates per room per night are always fixed and cost $40, $20 and $55 for Hotels, Hostels and Bed-n-Breakfasts respectively.The skeleton code for an inheritance hierarchy that models this scenario is stubbed out below. Complete all missing parts so that the code compiles, models the inheritance hierarchy, and has all the functionality described above. You should decide which classes the appropriate data members are stored in, and the types of those data members. In every class, complete theconstructor and provide a method, computeRate,which takes as parameter the number of nights spent and returns the total room rate for that lodging.No other methods should be provided.
Can someone give me some tips on weather you think I am going about this problem in the right way. the main thing that I am having issues with is the computeRate method. Im not sure how to set the prices of the Lodgings for hotels, Bed-n-Breakfasts, and hostels. I tried using super but im not completely sure if thats what I am supposed to do.
// parent class
public class Lodging
{
int sum;
int price;
public Lodging( int price ) {
this.price = price;
}
}
public double computeRate(int numberOfNights){
price *= numberOfNights;
return sum;
}
// child class
public class Hostel extends Lodging
{
private int numberOfRooms;
private boolean bikeRentals;
public Hostel( int rooms, boolean rentals) {
super(20);
this.numberOfRooms = rooms;
this.bikeRentals = rentals;
}
}
// child class
public class Hotel extends Lodging
{
private int rooms;
private int starRating;
public Hotel( int rooms, int starRating ) {
super(40);
this.rooms = rooms;
this.starRating = starRating;
}
}
// child class
public class BednBreakfast extends Lodging
{
private int numberOfRooms;
private boolean lateArrivals;
public BednBreakfast( int rooms, boolean late ){
super(55);
this.numberOfRooms = rooms;
this.late = late;
here is the given skeleton code
class Lodging
{
public Lodging( )
{
}
}//End class Lodging
class Hotel
{
public Hotel( )
{
}
}//End class Hotel
class Hostel
{
public Hostel( )
{
}
}//End class Hostel
class BednBreakfast
{
public BednBreakfast ( )
{
}
}//End class BednBreakfast
Each of your classes has rooms, so I would move that to the parent class, and add it to the constructor.
Also, a Lodging is an abstract concept, so you cannot make a new Lodging(), you need a specific instance of one.
public abstract class Lodging {
private double nightlyRate;
private int capacity;
public Lodging( int capacity, double rate ) {
nightlyRate = rate;
this.capacity = capacity;
}
public double computeRate(int numberOfNights){
return this.nightlyRate * numberOfNights;
}
}
Then, there's nothing wrong with super(rooms, 20), for the Hostel example. It's correctly setting up the parent class's fields, and each subclass will inherit the super class's computeRate() method. The problem description doesn't indicate it needs to be overriden.

Creating an abstract base class for handling different type of enums

Currently I have several enums defined over several classes. They all look similar to the one shown below:
public class ApaMessage {
private String apaMessage;
private final int FIXED_LENGTH_SIZE=39;
public enum ApaFields {
FIELD1(ApaUtils.ApaFieldTypes.POSITION_BASED, null, "field1", 2, 3, false, false),
private final ApaUtils.ApaFieldTypes type;
private final String ApaName;
private final String jsonName;
private final int start;
private final int finish;
private boolean required = false;
private boolean withDelimiter = false;
ApaFields(ApaUtils.ApaFieldTypes type, String ApaName, String jsonName, int start, int finish, boolean required, boolean withDelimiter) {
this.type = type;
this.ApaName = ApaName;
this.jsonName = jsonName;
this.start = start;
this.finish = finish;
this.required = required;
this.withDelimiter = withDelimiter;
}
}
There is also a method defined in ApaMessage:
private HashMap<String,Object> getApaJsonFieldsAndValues() {
HashMap<String, Object> jsonApaData = new HashMap<String, Object>();
for (ApaFields field : ApaFields.values()) {
jsonApaData.put(field.jsonName, getApaFieldValue(field));
}
return jsonApaData;
}
The problem is although there isn't a lot of code, I will soon have 10-20 of these enums. I would like to create an abstract base class where the HashMap method, and other similar methods can be part of. The base class should accept an ApaFields enum and other enums and do what the getApaJsonFieldsAndValues does. The problem is, how can the base class access the passed enum values and the internal fields such as jsonName to do the loop?
I have tried different approaches but the main problem is that the base class cannot seem to access the values. Is there any way around this? Alternatively, is there a better approach? Thanks
EDIT:
Basically I would like something like this in the base class. Note the below doesn't compile.
public abstract class ApaRequestMessage {
private Class<? extends Enum<?>> apaRequestMessageFields;
private String apaMessage;
public <T extends Enum<T>> void ApaRequest(Object apaRequestFields, String apaMessage) {
apaRequestMessageFields = (Class<? extends Enum<?>>) apaRequestFields;
this.apaMessage = apaMessage;
for (Field field: apaRequestMessageFields.values()) {
//this doesn't work because it cannot access the values of apaRequestMessageFields
}
}
}
And then call the base method as follows, although not sure if this is correct, where ApaFields is the inner enum defined above.
ApaRequest(ApaFields.class, somestringmessage);
I came across something similar when trying to define a db schema using enums as columns in the table. I eventually took this route.
Define a base class with sufficient generic signature to ensure the enum is properly built.
public class Table<Column extends Enum<? extends Column>> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
Now extend this for each table - here is a simple VersionTable:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
Now you have all of the core functionality in the base class and all the sub-classes need to do is implement the interface on the enum.
I realise this does not address the issue of duplicated bolierplate code in all of your enums but it does move alomst all of it elsewhere.

Using reflection to get a specific attribute from a extended instance

I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.

Categories

Resources