Hi want to add new field boolean hasXYZ to an existing class which has two member variables. This class is widely used in the code and I want to add the new field in a way that I do not want to change all of the
new demoClass() calls to include the new field hasXYZ. And I was hasXYZ more like a on demand field .. so effectively, I guess two set of constructor .. one which works and other which takes additional boolean and sets hasXYZ. Thoughts on how I can do this ?
#Value
#NonFinal
public class demoClass implements demoInterface {
int integerMember;
long longMember;
}
Overload the constructor:
public class demoClass implements demoInterface {
int integerMember;
long longMember; // these should probably be private
boolean hasXYZ;
public demoClass( int integerMember, long longMember) {
this.integerMember = integerMember;
this.longMember = longMember;
}
public demoClass( int integerMember, long longMember, boolean hasXYZ) {
this.integerMember = integerMember;
this.longMember = longMember;
this.hasXYZ = hasXYZ;
}
}
Then you won't have to modify how you create the objects.
Related
I was wondering lately, which one of the three methods of passing parameters to the method - presented below - are the best for you, your CPU, memory and why. I am considering methods which allow me to pass more arguments in future, without changing the method signature.
If you know something better, I am here to listen and learn.
Pass by methods
Params.java
public interface Params {
int getParamOne();
int getParamTwo();
}
Calling
obj.foo(new Params() {
#Override
public int getParamOne() {
return 1;
}
#Override
public int getParamOne() {
return 2;
}
});
Receiving
public void foo(Params p) {
int p1 = p.getParamOne();
int p2 = p.getParamTwo();
}
Pass by class fields
Params.java
public class Params {
private int paramOne;
private int paramTwo;
// Getters and setters here
}
Calling and receiving
No magic here, just create a new Params object, use setters, pass it to the method and use getters.
Pass by Properties class
Calling
properties.put("paramOne", 1);
properties.put("paramTwo", 2);
obj.foo(properties);
Receiving
public void foo(Properties properties) {
int a = (int) properties.get("paramOne");
int b = (int) properties.get("paramTwo");
}
I was pleased to show an real-life example of code, which actually needs passing varying types and number of properties. I'm using the third method - passing by the properties:
public interface DataProvider {
public String getContent(Properties properties);
}
public class HttpProvider implements DataProvider {
#Override
public String getContent(Properties properties) {
InputStream in = new URL(properties.get("URL")).openStream();
String content = IOUtils.toString(in);
IOUtils.closeQuietly(in);
return content;
}
public class FtpProvider implements DataProvider {
#Override
public String getContent(Properties properties) {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(properties.get("server"), properties.get("port"));
ftpClient.login(properties.get("user"), properties.get("pass"));
// Get file stream and save the content to a variable here
return content;
}
}
One interface for a different methods of obtaining a file. I am not persisting that this is good or not, it's just an example of code I've stumbled upon in my current project in work and I was wondering if could it be done better.
The usage of a "Params" class is better than properties, in performance. The java compiler can handle such short lived classes quite well.
One sees properties on some constructors / factory methods, like for XML and such.
One sees a parameter containing class in larger systems, to keep the API restricted to one parameter, and not use overloaded methods.
I would do:
public class Params {
public final int a;
public final int b;
public Params(int a, int b) {
this.a = a;
this.b = b;
}
}
And in the class immediately use params.a.
For the rest there is also the Builder Pattern, but that would be more a substitute for a complex constructor.
Signatures in interfaces should not ever change!!! If you contemplate to change APIs in the future (i.e. change, add or remove a parameter), an acceptable way may be by incapsulating your parameters in objects in order to do not break signatures.
This class is where I want to call the arrays and set the arrays to empty within the parameters
public class ElectronicsEquipmentSupplier {
private int currentMonth;
private int currentYear;
private String rangeOfProducts;
private CustomerDetailsList details; //Contains the customer details array
private PurchaseOrderList pal; //Contains the purchase array
public ElectronicsEquipmentSupplier(int currentMonth, int currentYear,
String rangeOfProducts ) {
this.currentMonth = currentMonth;
this.currentYear = currentYear;
this.rangeOfProducts = rangeOfProducts;
}
}
This is the class where the array is created. It pulls information from a separate class called PurchaseOrder and then sets the list.
public class PurchaseOrderList {
private ArrayList<PurchaseOrder> purchaseCollection;
public PurchaseOrderList() {
purchaseCollection = new ArrayList<PurchaseOrder>();
}
The CustomerDetailsList class is essentially the same. Just not sure as to the best way to set the array to empty when called in the ElectronicsEquipmentSupplier.
Simply wrap the collection's own clear() method with a publicly-accessible method in your PurchaseOrderClass:
public class PurchaseOrderList {
private ArrayList<PurchaseOrder> purchaseCollection;
public PurchaseOrderList() {
purchaseCollection = new ArrayList<PurchaseOrder>();
}
//THIS IS THE IMPORTANT PART
public void clearPurchaseCollection() {
purchaseCollection.clear();
//You could also accomplish the same thing by reinitializing the list:
//purchaseCollection = new ArrayList<PurchaseOrder>();
}
}
Note however, that calling new PurchaseOrderList() already guarantees an empty purchaseCollection list, since you initialize it in the constructor that way.
So the only time you would need to call clearPurchaseCollection() is if you are reusing this object and want to clean it out first. Depending on the rest of your application, that may be necessary, but it may also just be simpler to throw away that instance and create a new PurchaseOrderList(). Totally depends on the situation.
I'm working with the Java AWS API to monitor some EC2 instances and on every refresh I need to query the service which returns a bunch of Instance objects (freshly constructed). I want to extend the functionality of these objects, I figure I can maintain a map of MyInstance objects which can be refreshed with the new Instances on each poll.
Now I could easily do this with a simple wrapper class that holds the original Instance as a property the issue is I would like to keep access to the base Instance API as I already use these functions in my code. Would it be possible to replace only the super-class parts of an instantiated object? Contrived example of what I'm going for:
class Instance {
protected int prop;
public Instance(int prop) {
this.prop = prop;
}
}
class MyInstance extends Instance {
protected int prop2;
public MyInstance(int prop, int prop2) {
super(prop);
this.prop2 = prop2;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.prop == 3
Obviously this example would be trivial to transform but in my actual case there are far more properties that need to be transferred. Can Reflection do this? What kind of performance impact am I looking at if I use Reflection for 10 of these every second? Thanks for reading!
The best solution is to combine both your ideas:
Wrap the original Instance in a class that extends the Instance class. (In the constructor of the child class, you can create a new Instance object and set it)
Delegate all methods to the wrapped instance (and add new properties)
In your foster method, you simply change the wrapped Instance.
class Instance {
private int prop;
public Instance(int prop) {
this.prop = prop;
}
public int getProp() {
return prop;
}
}
class MyInstance extends Instance {
private Instance delegate;
private int prop2;
public MyInstance(Instance delegate, int prop2) {
super(prop);
this.delegate = delegate;
this.prop2 = prop2;
}
#Override
public int getProp() {
return delegate.getProp();
}
public int getProp2() {
return prop2;
}
public void foster(Instance i) {
delegate = i;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.getProp() == 3
I'm just starting my first steps with Java, learned all the basics but then found a problem with an enum I need, so forgive me, if the solution to my problem is something very obvious:
So I've got this enum and want to add a unique id to each instance counting from 0 upwards, but without having to add another parameter to each constructor calling (because this can later on lead to errors ofc).
public enum TerrainTile{
WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(99);
private final int id;
private final int moveCost;
private boolean hidden = true;
private TerrainTile(int moveCost) {
this.moveCost = moveCost;
}
And I thought to just add a
static int nextID = 0;
and edit the constructor to
private TerrainTile(int moveCost) {
this.id = nextID++;
this.moveCost = moveCost;
}
But I get an error message that it can not refer to a static field inside the initializer.
Is there any workaround?
You can use the ordinal() method for it. It is based on the order in which the members are declared in the source-code and counted from zero. So I guess, exactly what you need.
Just a note:
You can get your original enum member from ordinal number by calling .values()[index]
example:
int hillOrdinal = TerrainTile.HILL.ordinal(); // 2
TerrainTile hill = TerrainTile.values()[hillOrdinal];
It sounds like you are trying to combine class features into an enum. I'd be particularly wary of non-final, non-static member fields in an enum declaration. The behaviour you want seems to be best served by using a TerrainTile class (possibly a flyweight if you truly want the single-instance-per-type behaviour) and a TerrainTileType (or TerrainTile.Type) enum. Something like this:
public class TerrainTile {
public enum Type {
WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(-1);
public final int MOVE_COST;
private TerrainTile(int moveCost) {
this.MOVE_COST = moveCost;
}
public boolean isTraversable() {
return (MOVE_COST > 0);
}
}
private final Type type;
private final Image texture;
...
private TerrainTile(Type type) {
this.type = type;
}
private static final Map<Type, TerrainTile> tiles = new EnumMap<>();
static {
// instantiate one TerrainTile for each type and store into the tiles Map
for (Type type: Type.values()) {
// Eventually, also load tile textures or set Color in this step
tiles.put(type, new TerrainTile(type));
}
}
public static TerrainTile getTile(Type type) {
// return the reference to the TerrainTile of this type
return tiles.get(type);
}
...
}
So I'm trying to cut back on some of the code that's been written. I created a separate class to try this. I have that class working correctly, however the old one uses variables that are now in the separate class. How do I access these variables? Unfortunately I can't share all the code for this, but I can give out small pieces that I think are necessary. Thanks for the help
This is from the old class that I am now trying to bring the variable to: I'm trying to bring "loader" over
// XComponentLoader loader = null;
fixture.execute(new OpenOfficeOpener());
component = loader.loadComponentFromURL("file:///"+System.getenv("BONDER_ROOT") + "/ControlledFiles/CommonFiles/"+spreadsheet, "_blank", 0, loadProps);
You can write getters for the members that you need to be visible outside. Example:
public class MyClass {
private int member1;
private String member2;
public int getMember1() {
return member1;
}
public String getMember2() {
return member2;
}
}
Now both member1 and member2 can be accessed from the outside.
There are a couple of solutions to your problem. What I would suggest is to add a method in your class to return the value to the new program, or pass it as a parameter.
An example of this on a higher level might look like this:
x = newClass.getValX()
It sounds like you're looking for a static field, though if is the case you almost certainly reconsider your current design.
public class YourClass {
private static XComponentLoader loader;
public YourClass() {
YourClass.loader = new XComponentLoader();
}
}
And to access it from another class:
public YourOtherClass {
public void yourMethod() {
YourClass.loader ...
}
}
If loader is static, than do something like:
component = TheOtherClass.loader.loadComponentFromURL( ...
Otherwise, your new class needs a reference to an instance of the other class. You could pass it with the constructor:
public class NewClass {
private OldClass oldClass = null;
public NewClass(OldClass oldClass) {
this.oldClass = oldClass;
}
// ...
fixture.execute(new OpenOfficeOpener());
// assuming, loader is a public field on OldClass.
// a getter (getLoader()) is preferred
component = oldClass.loader.loadComponentFromURL("file:///"+System.getenv("BONDER_ROOT") + "/ControlledFiles/CommonFiles/"+spreadsheet, "_blank", 0, loadProps);
// ...
}
I've you've split functionality into two classes, then you may want to have one class instantiate another.
If you've put your new code in Class B then it might look like this.
public class A {
// Class B instance
B b = new B();
public void doSomething() {
b.loadComponentFromURL("someurl");
}
}
Or if the loader is an instance itself, you could call it like this.
b.getLoader().loadComponentFromURL("someurl");