Java, enum with constructor - java

I'm refactoring some legacy system written in Java, and I came across a problem with an enum constructor.
I have an enum class like this (just an example):
public enum Signal{
ON(new InButton()),
OFF(new OutButton())
private final Button button;
Signal(Button button) {
this.button = button;
}
}
InButton and OutButton extends the Button interface.
The enum values are accessed for the first time using Signal.Values() method.
(Also, in one of the Button method, I have a code that uses the enum, such as activateButton(Signal.ON))
While refactoring the code, I wanted to create a new constructor for Button that express it dependency, such as Button(String input).
The problem is that I don't know how to pass the new parameters to the enum button field.
What is the right way to deal with this situation?
Is this enum should be used at all?
Clarification after Jean Logeart question: InButton and OutButton also have a constructor with a String arguments.
I'd rather avoid it to be initialize to null because than it could create other problems.
Basically this question is how to mimic a=f(x) using java syntax. Most of the time I can do:
y = new x(); a = new f(y);
a = new f(new x());
a = new f(null); a.getF().setX(new x());
In this case I can't do it.

I suggest not having the enums know about the buttons at all. Just have them enumerate the possible signals, and put the job of mapping signal->button somewhere else:
Function<Signal, Button> signalToButton = ...
That will also make it easier to inject different buttons for testing; for instance, you can inject a mocked Button that confirms that it was our wasn't pressed.
As far as using that mapping in your code: you can "install" a mapping to some static field, or, better yet, provide it as a constructor argument to any code that needs it. Dependency injection is very helpful for the latter option, but that may be a bigger change.

Two main options.
First one, InButton and OutButton also have a constructor with a String argument in which case you need to provide a String when instanciating:
public class InButton extends Button {
public InButton(String s) {
super(s);
}
}
// ...
public enum Signal{
ON(new InButton("in"))
// ...
}
Second option, InButton and OutButton are instanciated with a specific String in which case no refactoring is necessary in the enum:
public class InButton extends Button {
public InButton() {
super("in"); // default value
}
}
// ...
public enum Signal{
ON(new InButton()) // same as before
// ...
}

Related

How to "refresh" the set-get of a class from one subclass of another class (Sorry for the poor title)

I will try to explain as well as I can the problem I'm dealing with.
SO I have a substract class "WeaponCarrier" in which I have a weapon.
That "Weapon" is a class that has a "void setHolder(WeaponCarrier holder){this.holder = holder}.
That "Weapon" class also has a "WeaponCarrier getHolder(){return holder;}" method.
What I'm trying to do is change the weapon setHolder/getHolder through a subclass in WeaponCarrier.
Something like:
private class sword extends WeaponCarrier
{
void methodName(){ weapon.setHolder(weapon.holder);} //This code doesn't work but I have tried a lot of things and nothing seemed to work either
}
The result I want is: When I "System.out.println(getHolder)" I want to get the new value from setHolder that I gave through the subclass.
I will take this question down if it doesn't make any sense to you.
Thank you so much for your valuable time.
You could use an abstract class weapon and use an instance of that.
Then use code like this
public abstract class Weapon{
Weaponcarrier holder;
String name;
//this creates the name var for the weapon
public Weapon(String name){
this.name = name;
//this sets the name that gets coded for the weapon to the instance of the weapon.
}
public void setHolder(weaponCarrier){
this.holder = weaponCarrier;
}
public Weaponcarrier getHolder(){
return this.holder
}
}
Then to make a sword(for example)
public class Sword extends Weapon{
public Sword(){
super("Sword"/*the name*/);
}
now make a list where you add all Weapons to called weaponlist and add all weapons to that.
Then make a function which returns the weapon's class when called.
Then you can use that class to call the functions for that one instance. This is scalable to include all weapons that you want to use. if you don't understand the second part you can just ask and I will tell you the code for that.
Then you can enter the one you want to set it to between the brackets and it sets it to that. Also make sure you put the right new in because now it is setting itself to what it currently is
This code does not work ...
If we look closely at this line ...
void methodName(){ weapon.setHolder(weapon.holder);}
... then we will see that it makes no sense, because the weapon object is setting a value on its field equal to its current value. It does not change anything ever.
If you change this line to something more useful, then you can do an override of a getter or a setter in the same way you would override any other method.
Ideally, you should cover your code by unit tests to ensure that it works exactly how you invisioned it.

Abstract class and Interface instantiation performance in Java

Let's say I want to create a Button class, I have two options :
abstract class Button {
Button() { }
abstract void action();
}
When the button is pressed, action() will be called, in that case I would instantiate my Buttons like that :
new Button() {
void action() {
...
}
};
The other option is :
interface ButtonAction {
run();
}
class Button {
ButtonAction action;
Button(ButtonAction action) {
this.action = action;
}
}
When the buttons is pressed, action.run() will be called, and I will instantiate the buttons like that :
new Button(new ButtonAction() {
void action() {
...
}
};
My question is, is there a bad and a good way, or it only depends on me? Is there a performance difference between those two buttons instantiation (I will often have to instantiate bunches of buttons)?
I would not worry about micro optimizations of performance like this. This decision will not have any meaningful impact on your app peformane.
I would, however, use the section option where you pass in an action to the constructor for a few reasons. It decouples concerns. Your button object should not have to worry about the details of what action it has to perform. What if you want to add a setter to change the action? Then the abstract method option breaks down. The second option also makes it easier to test the action separately from the button. In general, favor delegation over inheritance.
There's no very big performance difference for this cases. But you should remember, that abstract classes are used to hold common logic, i.e. you want to print some message after every action performing. If there's no common logic you should use interfaces.

How do you add new functions to pre-existing java components?

To explain what I mean by this question I will use code examples below. Imagine you have this function.
private void fadeButton(JButton b, int timeToFade) {
//Fade code goes here
}
How would you implement this as a function which could be run like
JButton b = new JButton("Press Me");
b.fadeButton(20000);
Where fadeButton now looks like
private void fadeButton(int timeToFade) {
//Fade code goes here
}
Because the function is declared on the button itself.
Typically you create a derived class:
public JFadableButton extends JButton
This will contain the method private void fadeButton(int timeToFade).
Short answer is: you don't.
Longer answer:
You can't do that in Java directly (adding methods to a class outside of the source code of that class). That might be different in other languages, like Kotlin offers "something" like that.
In java, you have to make detours, for example by turning to the decorator pattern.
And just for the record: I didn't mention the simple "you can extend that class" because I read your question as "how do I add methods to JButton directly". But of course, creating your own class that extends JButton allows you to add methods; but of course, they only exist on objects of your derived class.
You could extend JButton with a new class, thus inheriting JButton's methods and adding the ability to add your own code:
public class FadingButton extends JButton {
//Constructors go here
private void fadeButton(int timeToFade) {
//Fade code goes here
}
}
You could also decorate the JButton with another class:
public class JButtonDecorator {
private JButton btn;
//Constructor here
private void fadeButton(int timeToFade) {
//Fade code goes here, hiding the held button
}
//getter and setter method for button
}
Or, if you want lots of different ways to affect your UI, you can make a utility class, similar to above:
//You could use a factory pattern to make this a singleton instead of having static methods
public abstract class UIUtils {
private UIUtils{} //Don't instantiate this class
public static void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other static utility methods
}
Edit: Making use of these patterns. The extended class is self-explanatory and an example of simple inheritance, so it's just a matter of JButton btn = new FadingButton(); for example. Here are the others:
To use the decorator, instantiate it at the same scope as the button you're using now. For example:
JButton myButton = new JButton();
//Customize button and add to UI
JButtonDecorator jbDec = new JButtonDecorator(myButton);
jbDec.fadeButton(20000);
Although the button is a field of the decorator, it will otherwise behave normally in your UI. The decorator just wraps the class with useful methods such as the fadeButton method.
To use the utility class, there are two ways. One is two make an abstract class with static methods (as above), some consider it bad form but it's good for simple programs:
UIUtils.fadeComponent(myButton); //It's just that simple!
//The UIUtils class itself is never instantiated.
//All the methods are static, so no instances are needed.
Or if you want a more advanced method, make your utility class a singleton. This changes the utility class to this:
public class UIUtils {
UIUtils singleton;
private UIUtils{} //Don't instantiate this class publicly
public static UIUtils getInstance() {
if(singleton==null) //This is the first time the method is called
singleton = new UIUtils();
return singleton; //Return the one instance of UIUtils
}
public void fadeComponent(JComponent toFade) {
//Fade code goes here
}
//Other utility methods
}
Then you would declare your UIUtils object at class level to use across your UI:
UIUtils uiUtil = UIUtils.getInstance();
And somewhere in your code:
uiUtil.fadeComponent(myButton);
This pattern is more efficient with memory and is more object-oriented, but I don't personally find it very suitable for utility classes.
You can create a new class which extends JButton, and then add any method that could help you achieve what you want. But that's an exemple, there is many ways to achieve this.
Ps, don't set this method as private if you want to use it somewhere else than inside your class.
This is the simplest way I think think of. You have already got it. But just use this method:
private void fadeButton(int timeToFade) {
//Fade code goes here
}
This is assuming you already have the code for the fade, do you? I think this one is the one you should use. You don't need the button to be a parameter. When you want to call the method to fade the button, just put it in the ActionListener. So after you have the ActionListener for the button, do the following: btnName.fadeButton(timeToFade);
Here is how to code the ActionListener:
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
}

Making objects for each button

I need to make objects for my buttons in my typing tutor.
I have made a class:
public class KeyLabel extends JLabel {
public KeyLabel(String name) {
setText(name);
}
this is my subclass
my superclass is the keyboard class
and I need to make objects for each button on my keyboard for my typing tutor, so the a is a label its the keyboard
but I don't know how to do this?
I don't know why are you extending JLabel if you are to create Buttons. Extending JLabel will create a JLabel which will be wasted as in your code. More relavent code would be like
public class KeyLabel {
public KeyLabel(String name) {
JButton buttonOK = new JButton("OK"); //creates OK button
}
}
Moreover, i think you should look here, for details.
In most cases, you'll want to use inheritance (i.e. subclass JButton). For instance,
public abstract JKeyboardButton extends JButton{
public JKeyboardButton(final String key){
super(key);
// include other stuff, if necessary
}
// include other methods common to all JKeyboardButton instances
}
And then for each concrete button, you'll want to subclass JKeyboardButton, like so
public final class JKeyboardAButton extends JKeyboardButton{
public JKeyboardAButton(){
super("a");
}
// override/implement other methods..
}
And then in order to obtain a keyboard key of, let's say a, all you have to do is create an instance of JKeyboardAButton, like so
final JKeyboardButton aButton = new JKeyboardAButton();
And then obviously you'll have to create a class for each key and throw all these instances into a Keyboard class. But I'll leave the "heavier" coding to you.
Also, please note that the final modifier is not required, but rather is a personal preference of mine (i.e. to prevent subclassing and to ensure that a variable (even local ones) are only assigned once).

How do I extend a java class that is instantiated by another class?

Given two java classes, A and B, where A is usually instantiated via B, such as:
A myA = B.createA();
Can I create a subclass of A (let's call it SubA) and somehow have it be instantiated by the B.createA() method?
(Note that I cannot modify A and B....)
I know that not all instances of A are instances of SubA, thus I cannot do this:
SubA mySubA = B.createA();
Similarly, I cannot cast it like this either:
SubA mySubA = (SubA) (B.createA());
for the same reason -- it will get a ClassCastException.
Am I being dense and forgetting something fundamental, or is there no way to do this?
(Late addition: I'm so sorry, I should have mentioned that A and B have roughly 50 methods each, and all I want to do is add a single property to SubA, along with a getter and a setter. I'd really rather not implement all 50 of A's methods to invoke the corresponding method in the superclass's object.)
It sounds like like what you'd really like is to modify the behavior of both the original A and B. In that case, you could try extending both classes (where the extension of B is purely to specify a slightly different factory method for creating SubAs).
class SubA extends A {
/** This is the one special aspect of SubA justifying a sub-class.
Using double purely as an example. */
private double specialProperty;
public double getSpecialProperty() { return specialProperty; }
public void setSpecialProperty(double newSP) { specialProperty = newSP; }
public SubA() {
super();
// Important differences between SubAs and As go here....
// If there aren't any others, you don't need this constructor.
}
// NOTE: you don't have to do anything else with the other methods of
// A. You just inherit those.
}
class SubB extends B {
// Purely for the purposes of a slightly different factory method
public A createA() {
return new SubA();
}
// Or if you need a static method
// (this is usually instead of the first choice)
public static A createA() {
return new SubA();
}
}
Note that at this point, you could create one of your SubB factory objects and make it look like the original B like so:
B myNewB = new SubB();
A myA = myNewB.createA();
Or, if you're using the static factory instead, it isn't quite as close a match (but it's close).
A myA = SubB.createA();
Now, if you really need to do something with the sub-property, you'll have access to it via the child interface. I.e., if you create the object like so:
SubA mySubA = SubB.createA();
mySubA.setSpecialProperty(3.14);
double special = mySubA.getSpecialProperty();
Edit to discuss "Late addition":
At this point, your SubA object should be exactly what you want. It will inherit the 50 methods from the parent (A) and you can add your additional property to the child, plus the getter and setter. I changed the code above to illustrate what I mean.
This is usually done via a proxy:
class SubA extends A {
private A proxiedClass;
public SubA(A a) {
proxiedClass = a;
}
public int anyMethodInA() {
return proxiedClass.anyMethodInA();
}
}
...
SubA mySubA = new SubA(B.createA());
Doing this manually is rather verbose, so most people use some kind of a AOP library (like AspectJ) to only intercept method calls they are interested in.
You could create a wrapper around it, with SubA having a constructor that takes A as the parameter.
Like this:
SubA mySubA = new SubA(B.createA());
Since all instances of SubA are instances of A, you could then assign it to your existing A variable and override any necessary methods.
A myA = new SubA(B.createA());
I can't think of any other clean way of doing it.
If you are just wanting to add a field to A without object oriented such as changing behaviour, you could add it as an "external field". Use a WeakHashMap to map from instance of A onto the field value (just so long as the field value doesn't directly or indirectly reference A or you'll have an object life time contention issue):
private static final Map<A,FieldType> map =
new java.util.WeakHashMap<A,FieldType>(); // thread-safe from 1.6, IIRC
public static FieldType getField(A a) {
return map.get(a);
}
public static void setField(A a, FieldType value) {
map.set(a, value);
}
Really we should be using WeakIdentityHashMap, but it doesn't exist in the Java library!

Categories