简体   繁体   中英

Is it bad practice to return Enums in Java?

Lets say I have a class to model an item in a game like so:

public class Item {
    private final EnumItem type;
    
    public Item(EnumItem type) {
        this.type = type;
    }
        
    public Item(String name) {
        this.type = EnumItem.fromName(name);
    }
}

public enum EnumItem {
    MACHINE_GUN("machine_gun"),
    SWORD("sword"),
    BAT("bat"),
    DEFAULT("default");
    
    private final String name;
    
    public EnumItem(name) {
        this.name = name;
    }

    public String getName() { return name; }

    public static EnumItem fromName(String name) {
        for(EnumItem i: EnumItem.values()) {
            if(i.name.equals(name)) {
                return i;
            } else {
                return EnumItem.DEFAULT;
            }
        }
    }
}

Assume that .equals() and .hashCode() of Item are overridden correctly to compare the internal Enum.

Now I want a way to distinguish these items with a getter in Item : should I return an Enum or the String name? Is it good practice to return an Enum in general? Or is there a better way to distinguish these Item s? Because returning the enum kind of looks like exposing the rep to me and I don't want my colleagues to use EnumItem directly to compare Item s.

The approaches I thought of are the following:

  1. string getName() to do something like item1.getName().equals("machine_gun") ;
  2. EnumItem getEnum() to do item1.getEnum().equals(EnumItem.MACHINE_GUN) ;
  3. item1.equals(new Item("machine_gun")) ;
  4. static name(String name) { new Item(name) } to do item1.equals(Item.name("machine_gun")) ;

I don't know what should I do, I'd appreciate some insight from experienced programmers.

I know they look like they would from context, but in my use case these items have no special functionality that would justify extending from the base Item class.

Is this good practice? Sure, you're using aggregation since Item doesn't depend on EnumItem, which is fine. That being said, could it be done better? Sure. Is the alternative I provide the only solution? No.

Alternative

If you want this to be extensible, consider using an interface to represent an item. Then allow the interface to extend this interface to provide some standard types. Alternatively you could use composition or aggregation to define a type inside EnumItem that implements the Item interface to ensure that equals/hashcode for the Item are always override and adhere to some contract.

interface Item {

    String key();

}

enum EnumItem implement Item {

    private final String key;

    EnumItem(String key) {
        this.key = key;
    }

    @Override
    public String key() {
        return key;
    }

}

class AbstractItem implements Item {
    
    // constructor, override name()
    
}
Item item = EnumItem.FOO_BAR;

Item item2 = new AbstractItem("FooBar");

Item item3 = () -> "FooBar";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM