Implementing toString on Java enums - java

It seems to be possible in Java to write something like this:
private enum TrafficLight {
RED,
GREEN;
public String toString() {
return //what should I return here if I want to return
//"abc" when red and "def" when green?
}
}
Now, I'd like to know if it possible to returnin the toString method "abc" when the enum's value is red and "def" when it's green. Also, is it possible to do like in C#, where you can do this?:
private enum TrafficLight {
RED = 0,
GREEN = 15
...
}
I've tried this but it but I'm getting compiler errors with it.
Thanks

You can do it as follows:
private enum TrafficLight {
// using the constructor defined below
RED("abc"),
GREEN("def");
// Member to hold the name
private String string;
// constructor to set the string
TrafficLight(String name){string = name;}
// the toString just returns the given name
#Override
public String toString() {
return string;
}
}
You can add as many methods and members as you like. I believe you can even add multiple constructors. All constructors must be private.
An enum in Java is basically a class that has a set number of instances.

Ans 1:
enum TrafficLight {
RED,
GREEN;
#Override
public String toString() {
switch(this) {
case RED: return "abc";
case GREEN: return "def";
default: throw new IllegalArgumentException();
}
}
}
Ans 2:
enum TrafficLight {
RED(0),
GREEN(15);
int value;
TrafficLight(int value) { this.value = value; }
}

Also if You need to get lowercase string value of enum ("red", "green") You can do it as follows:
private enum TrafficLight {
RED,
GREEN;
#Override
public String toString() {
return super.toString().toLowerCase();
}
}

I liked this approach for selective alternate toString() if it's useful for anyone out there :
private enum TrafficLight {
RED,
GREEN {
#Override
public String toString() {
return "GREEN-ISH";
}
}
}

Related

Switch String with Enum variables

I have got an Enum with different values and want to switch a string variable. Now I hit a wall trying to convert the Enum values to Strings, that I can use as case constant.
My best try was to convert the Enum to a String array, but the switch doesn't seem to accept array values as a case constant. (IntelliJ says: "constant expression required")
Enum myEnum = {FOO, BAR}
String input = "foo"
final String[] constant = Arrays.stream(myEnum.values()).map(Enum::name).toArray(String[]::new);
//converts Enum to String[]; made it final, so it is "constant"
switch (input) {
case constant[0]:
System.out.println("foo");
break;
case constant[1]:
System.out.println("bar");
break;
}
Is there an elegant way to make this switch depend on the Enum?
You shouldn't convert it because it isn't needed. Also, your code won't even compile because case is a reserved keyword in Java.
You should take a look at the valueOf method of an Enum.
Your code can look like that:
public enum MyEnum {FOO, BAR}
//method
String input = "foo";
MyEnum niceFound = MyEnum.valueOf(input.toUpperCase());
That will return FOO but can throw an IllegalArgumentException when the given value isn't present as type.
You can do this :
public enum MyEnum {
FOO("foo"),
BAR("bar");
private String value;
public String getValue() {
return value;
}
public static MyEnum getState(String value) {
switch (value) {
case "foo":
return FOO;
case "bar":
return BAR;
}
return null;
}
private MyEnum(String value) {
this.value = value;
}
}
Now, in your class, you can :
MyEnum myEnum = getState("foo"); // returns MyEnum.FOO
Also make sure you handle the case when getState() returns null
A solution with Java 8+ streams would be to create a method inside your enum :
public static Optional<MyEnum> getByValue(final String value) {
return Arrays.stream(MyEnum.values())
.filter(myEnum -> myEnum.value.equals(value))
.findFirst();
}
This returns optional in case there is no enum value for your String parameter. But you can change it according to your needs.
Use MyEnum.valueOf(value.toUpperCase())
public enum MyEnum {
FOO, BAR;
}
public static void process(String value) {
try {
switch (MyEnum.valueOf(value.toUpperCase())) {
case FOO :
System.out.println("FOO");
break;
case BAR :
System.out.println("BAR");
break;
default :
break;
}
}
catch (IllegalArgumentException e) {
// TODO: handle exception
}
public static void main(String[] a){
process("foo");
}

Mapping complex data from Model to View

Let's consider a simplified MVC architecture, where Model operates on different types of Confections. There are different subtypes of Confection class, such as Candy, Cookie, Doughnut, etc. Every subtype, in turn, has different sets of properties, like size, color, shape and so on.
For instance, that's one implementation of Candy class:
class Candy extends Confections {
public enum Size {
LARGE,
MEDIUM,
SMALL,
}
public enum Color {
RED,
GREEN,
YELLOW,
}
private Size size;
private Color color;
...
}
Now the Model wants to update the View with a new set of Confections to display. Let's say that the only thing View needs to get the picture of a Confection is a string representation of its type and properties, e.g. "candy_red_large". The dumbest thing to do this is to have a number of instanceof branches and switches for types inside the View:
if (confection instanceof Candy) {
result.append("candy");
switch ((Candy) (confection).color) {
case RED:
result.append("_red");
break;
...
}
...
} else ...
Besides this monster is large and ugly, it also doesn't benefit from encapsulation and OOP. Let's consider a better way of doing this by providing each Confection subclass with a method like toString(), which will return the desired string representation:
class Candy extends Confections {
...
public String toString() {
return ("candy_" + size + "_" + color).toLowerCase();
}
}
The only problem I see in this approach is some kind of architectural "trade-off" when Model is actually aware of View implementation details having toString method, which is useless from Model's point of view.
What would be the best approach or design patterns to use in such case for mapping diverse data from Model to View representation?
maybe use some to strings to get what you want:
class Confections {}
class Candy extends Confections {
public enum Size {
LARGE,MEDIUM,SMALL,
}
public enum Color {
RED,GREEN,YELLOW,
}
Candy(Size size,Color color) {
this.color=color;
this.size=size;
}
private Size size;
#Override public String toString() {
return "Candy [size="+size+", color="+color+"]";
}
public String toString2() {
return "candy_"+size+"_"+color;
}
private Color color;
}
public class SO53564342_mapping_complex_data_from_model_to_view {
public static void main(String[] args) {
Candy candy=null;
for(Candy.Size size:Candy.Size.values())
for(Candy.Color color:Candy.Color.values())
System.out.println((candy=new Candy(size,color)).toString()+" "+candy.toString2());
}
}
Idea
I could imagine to introduce a new interface StringRepresentation:
public interface StringRepresentation {
String represent();
}
StringRepresentation will be implemented by Confections. To foce every child of Confections to implement represent make it abstract:
public abstract class Confections implements StringRepresentation {}
After that we have to implement in Candy and the other classes represent. If you want to work with Enums you could let them implement StringRepresentation too.
Example of a String Representation in Candy
public class Candy extends Confections {
private Size size;
private Color color;
public String represent() {
return "candy_" + color.represent() + "_" + size.represent();
}
public enum Size implements StringRepresentation {
LARGE("large"),
MEDIUM("medium"),
SMALL("small");
private final String representation;
Size(String representation) {
this.representation = representation;
}
public String represent() {
return this.representation;
}
}
public enum Color implements StringRepresentation {
RED("red"),
GREEN("green"),
YELLOW("yellow");
private final String representation;
Color(String representation) {
this.representation = representation;
}
public String represent() {
return this.representation;
}
}
}
Benefit
You do not need to use conditions like switch or if and you do not need loops. In addition, each class/component - as above the enums and classes - has its own logic, so you know where to change a representation as you change in the future.

Looping over heterogeneous collection

The example is as follows: I have a Box that needs to be filled with some Things. I'm interested only in weight of each thing. Also, beside weight, I need to correctly identify the thing that I'm measuring. Each thing type has different Id type. In this case I have toys and fruits, which have ToyId and FruitId respectively. In the end, I need to be able to print thing identifier and thing weight.
Question: Is it somehow possible to access specific methods on ThingIds without using instanceof operator (as in example)?
class Color{}
interface ThingId {}
class FruitId implements ThingId {
String name; //"apple", "orange", ...
FruitId(String name){ this.name = name; }
String getName(){ return this.name; }
}
class ToyId implements ThingId {
String shape; //"square", "circle", ...
Color color; //"red", "blue"...
ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
String getShape(){ return this.shape; }
Color getColor(){ return this.color; }
}
class Thing{
ThingId thingId;
Integer weight;
public Thing(ThingId thingId, Integer weight){
this.thingId = thingId;
this.weight = weight;
}
ThingId getThingId(){ return this.thingId; }
Integer getWeight(){ return this.weight; }
}
class Box {
Set<Thing> things = new HashSet<>();
void addThing(Thing thing){
this.things.add(thing);
}
Collection<Thing> getThings(){
return this.things;
}
}
class Program {
public static void main(String[] args) {
FruitId appleId = new FruitId("apple");
Thing apple = new Thing(appleId, 1);
ToyId cubeId = new ToyId("square", new Color());
Thing cube = new Thing(cubeId, 22);
Box box = new Box();
box.addThing(apple);
box.addThing(cube);
for(Thing t : box.getThings()){
System.out.print("Thing Id is: ");
if(t.getThingId() instanceof FruitId) { //any other possibility than using instance of?
process((FruitId)t.getThingId());
}
if(t.getThingId() instanceof ToyId){ //any other possibility than using instance of?
process((ToyId)t.getThingId());
}
System.out.println("Weight is : " + t.getWeight());
}
}
static void process(FruitId fruitId){
System.out.println(fruitId.getName());
}
static void process(ToyId toyId){
System.out.println(toyId.getShape() + toyId.getColor());
}
}
UPDATE
OK, I think Visitor pattern could be useful here:
class Color{}
interface ThingId {
void visitThingId(ThingIdVisitor visitor);
}
class FruitId implements ThingId {
String name; //"apple", "orange", ...
FruitId(String name){ this.name = name; }
String getName(){ return this.name; }
#Override
public void visitThingId(ThingIdVisitor visitor) {
visitor.process(this);
}
}
class ToyId implements ThingId {
String shape; //"square", "circle", ...
Color color; //"red", "blue"...
ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
String getShape(){ return this.shape; }
Color getColor(){ return this.color; }
#Override
public void visitThingId(ThingIdVisitor visitor) {
visitor.process(this);
}
}
class Thing{
ThingId thingId;
Integer weight;
public Thing(ThingId thingId, Integer weight){
this.thingId = thingId;
this.weight = weight;
}
ThingId getThingId(){ return this.thingId; }
Integer getWeight(){ return this.weight; }
}
class Box {
Set<Thing> things = new HashSet<>();
void addThing(Thing thing){
this.things.add(thing);
}
Collection<Thing> getThings(){
return this.things;
}
}
class ThingIdVisitor{
void process(FruitId fruitId){
System.out.println(fruitId.getName());
}
void process(ToyId toyId){
System.out.println(toyId.getShape() + toyId.getColor());
}
}
class Program {
public static void main(String[] args) {
FruitId appleId = new FruitId("apple");
Thing apple = new Thing(appleId, 1);
ToyId cubeId = new ToyId("square", new Color());
Thing cube = new Thing(cubeId, 22);
Box box = new Box();
box.addThing(apple);
box.addThing(cube);
for(Thing t : box.getThings()){
System.out.print("Thing Id is: ");
t.getThingId().visitThingId(new ThingIdVisitor());
System.out.println("Weight is : " + t.getWeight());
}
}
}
I don't really get what you're trying to achieve. First of all, I don't get the use of the interface ThingId. Second, I think you're a bit confused about interfaces and inheritance. If I were you, I'd look up polymorphism.
Anyway, I propose you remove the ThingId interface and let the FruitId and ToyId classes extend the Thing class. As your collection only exists of Things, and as your Fruit and Toy classes all extend this Thing class and thus implement the getWeight() method, you should not use instanceof anymore.
But please, read up on polymorphism.
your interface ThingId must provide the respective methods that you want to have.
If you simple want to print out information, then you can use like a simple
public String getInformation();
Then the implementations can return the information that is relevant for them and you can simply work with ThingId in your application code.
BTW: As you are storing your Things in a HashSet make sure to implement equals and hashCode in all Thing implementations
Also I dont really see, why you need a Thing and a ThingId, as ThingId seems a bit more than a simple id and actually a thing. So for me it seems that ThingId is redundant and all can be achieved by the having different Things
Since you are calling the same method process on both the instance types, why not add that method to ThingId interface itself.
By doing so, you could just call:
t.getThingId().process();
Instead of finding the instance type and calling respective methods.

Enum with Strings

This is my enmun class
public enum CSSFont {
RezeptName("-fx-font: 22 calibri;"),
RezeptNameClicked("-fx-font: 22 calibri; -fx-underline: true; -fx-text-fill: purple"),
RezeptTab("-fx-font: 15 calibri;");
private String font;
private CSSFont(String s) {
this.font = s;
}
public String getFont() {
return this.font;
}
}
As you can see I created a getFont() function to get the String of each CSSFont object. Is there a way to directly make String objects in an enum class(I need the String for setStyle() methods in JavaFX), so that I don't have to always write CSSFont.object.getFont() but rather CSSFont.object? I tried to let CSSFont extend String, but obviously enums can only implement interfaces. Or is the only solution to create a class with static (final) String attributes?
EDIT: Thanks everybody, it seems I wasn't really sure when to use enums and when not to, since I have only one attribute(String) and I don't even need enumaration or comparison of these enum objects, I will use a class with static final string attributes ;).
You can use something like this:
public enum MyType {
ONE {
public String toString() {
return "this is one";
}
},
TWO {
public String toString() {
return "this is two";
}
}
}
Test it using:
public class EnumTest {
public static void main(String[] args) {
System.out.println(MyType.ONE);
System.out.println(MyType.TWO);
}
}
Originally taken from here
You can override toString method:
public enum CSSFont {
RezeptName("-fx-font: 22 calibri;"),
RezeptNameClicked("-fx-font: 22 calibri; -fx-underline: true; -fx-text-fill: purple"),
RezeptTab("-fx-font: 15 calibri;");
private String font;
private CSSFont(String s) {
this.font = s;
}
public String getFont() {
return this.font;
}
public String toString(){
return this.font;
}
}
Then you can get font as follows:
CSSFont.RezeptName.toString()

Is it correct to use enum in this case?

This is a question about best practice/style.
I have a Printer class that can print out an element with different colors. Is it correct to use an Enum as input like this:
public class Printer {
public enum Color{RED, GREEN, BLUE}
public void print (Color color){
MyElement myElement = new MyElement();
switch (color) {
case RED:
myElement.setColor("#xxxxxx");
break;
case GREEN:
myElement.setColor("#xxxxxx");
break;
case BLUE:
myElement.setColor("#xxxxxx");
break;
}
myElement.print();
}
}
And then just call the method from another class like this:
Printer p = new Printer();
p.print(Printer.Color.RED);
... or would it be better to add the values to enum like this:
public class Printer {
public enum Color {
RED("#xxxxxx"),
GREEN("#xxxxxx"),
BLUE("#xxxxxx");
private final String hex;
Color(String hex){
this.hex = hex;
}
public String getHex(){
return this.hex;
}
}
public void print (Color color){
MyElement myElement = new MyElement();
myElement.setColor(color.getHex());
myElement.print();
}
}
... or maybe not use enum at all and just use plain string?
I don't see any problem with your solution. The only thing I would would suggest is to create a constructor on the Enum and store the color value over there. But it's just a suggestion.
It would be like this:
public class Printer {
public enum Color{
RED("#FF0000"), GREEN("#00FF00"), BLUE("#0000FF");
private String colorAsString;
private Color(String colorAsString) {
this.colorAsString = colorAsString;
}
public String getColorAsString() {
return this.colorAsString;
}
}
public void print (Color color){
MyElement myElement = new MyElement();
myElement.setColor(color.getColorAsString());
myElement.print();
}
}
Using an enum in the place of constants usually makes sense. If the application is as simple as explained in the question, with only 1 parameter (the color value), using string constants is also efficient.
If an enum is to be used, the second approach (i.e., the one storing the color value via the enum constructor) is preferable.

Categories

Resources